Mostly from an email from Serge...

#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>

struct Base {
    virtual ~Base() {}
    virtual std::string name() { return "Base"; }
};

struct Derived : Base {
    virtual std::string name() { return "Derived"; }
};

void fun(std::vector<boost::shared_ptr<Base> > const & vec) {
    typedef std::vector<boost::shared_ptr<Base> >::const_iterator Itr;
    for (Itr i = vec.begin(), e = vec.end(); i != e; ++i) {
        std::cout << (*i)->name() << std::endl;
    }
}

// This works:
void call_fun_1() {
    std::vector<boost::shared_ptr<Base> > vec;
    vec.push_back(boost::shared_ptr<Base>(new Base()));
    fun(vec);
}

// So does this:
void call_fun_2() {
    std::vector<boost::shared_ptr<Base> > vec;
    vec.push_back(boost::shared_ptr<Derived>(new Derived()));
    fun(vec);
}

// But this does not:
void call_fun_3() {
    std::vector<boost::shared_ptr<Derived> > vec;
    vec.push_back(boost::shared_ptr<Derived>(new Derived()));
    fun(vec); // <-- compile time failure
}

int main(int argc, char ** argv) {
    call_fun_1();
    call_fun_2();
    call_fun_3();
}

So what I'm saying is that std::vector<boost::shared_ptr<Base> > can actually be filled with instances of boost::shared_ptr<Derived>. You cannot however pass off a std::vector<boost::shared_ptr<Derived> > as a std::vector<boost::shared_ptr<Base> >, because those two things are unrelated types.

In Python, so long as you do something like

vec = VectorOfBase?() vec.push_back(Derived()) ...

then things will work.