Take the 2-minute tour ×

Question1> Why the following code doesn't work?

Question2> What is the correct way to design it?

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

using namespace std;

class BaseClass

class SubClass : public BaseClass

int main()
    std::vector<boost::shared_ptr<SubClass> > vecSubClassShared;

    boost::shared_ptr<SubClass> sub1(new SubClass);


    // Error    1   error C2440: 'initializing' : cannot convert from 'std::vector<_Ty>' to 'const std::vector<_Ty> &`
    const std::vector<boost::shared_ptr<BaseClass> >& vecBaseShared = vecSubClassShared;
share|improve this question
My gut tells me that (if it's possible) it's an ugly solution, given the fact that just casting a single boost::shared_ptr<SubClass> to a boost::shared_ptr<BaseClass> requires static_pointer_cast –  Cornstalks Feb 27 '13 at 5:17
I have used a single boost::shared_ptr<BaseClass> which is initialized with boost::shared_ptr<SubClass> and it works as expected. Just curious, why the collection of such things doesn't work. –  q0987 Feb 27 '13 at 5:29
add comment

marked as duplicate by jogojapan, billz, Drew Dormann, WhozCraig, Sindre Sorhus Feb 27 '13 at 10:52


2 Answers

In the view of the C++ compiler, shared_ptr<BaseClass> and shared_ptr<DerivedClass> are different, unrelated types. While the compiler knows, that normal Pointers can be converted from Derived* to Base*, it does not know that conceptually the same should apply for shared_ptrs, because it does not know "smart pointers" being pointer-like.

The same applies for vector or for templates in general: two instantiations of a template are two different class, with no relation betwen them (if not designed explicitly). So the compiler sees a vector<Something> bound to a reference to a vector<SomethingElse> which are not related types, so the reference binding fails.

But even if the types were somehow related, the binding would fail:

long l = 5;
int& ir = l; //ERROR
share|improve this answer
add comment

shared_ptr<BaseClass> and shared_ptr<SubClass> are distinct, unrelated types, so there's no way for a vector of one to alias a vector of the other, because there's no guarantee that their object layout is the same.

This means that to e.g. pass const std::vector<boost::shared_ptr<BaseClass> >& to a function you'll have to construct a temporary vector of the desired type. You can however do this without incrementing the reference counts on the shared pointers, using shared pointer aliasing:

#include <vector>
#include <memory>

struct B {};
struct D: public B {};

template<typename T, typename U>
std::vector<std::shared_ptr<T>> shared_vector_static_cast(
   const std::vector<std::shared_ptr<U>> &v)
   std::vector<std::shared_ptr<T>> w;
   for (const std::shared_ptr<U> &p: v)
      w.push_back(std::shared_ptr<T>(std::shared_ptr<void>(), p.get()));
   return w;

int main() {
    std::vector<std::shared_ptr<D>> v{std::make_shared<D>()};
    const std::vector<std::shared_ptr<B>> &w = shared_vector_static_cast<B>(v);
share|improve this answer
There is a bug in the code. The size of w is the end is 2*v.size() rather than v.size(). –  q0987 Mar 5 '13 at 15:22
@q0987 cheers, fixed –  ecatmur Mar 6 '13 at 16:45
add comment
