user2487382
user2487382

Reputation:

Array of shared pointers to different classes

I'm trying to figure out if it is possible to create an array of shared pointers to different types. For example, something like that:

vector<shared_ptr<**???**>> v;
v.push_back(shared_ptr<int>(new int));
v.push_back(shared_ptr<MyClass>(new MyClass()));

or any other way to pass shared_ptr without knowing its type.

Upvotes: 17

Views: 3955

Answers (3)

JBL
JBL

Reputation: 12907

Assuming you want to store objects that do not inherit a common class, the simplest way that comes to mind is to use boost::any.

You still have to be sure about what's the type of each object stored at each index (i.e. to be able to perform the correct boost::any_cast).

You should do that rather than storing pointers to void. This is the closest as it gets to the semantically correct way of storing "something you know the type but the compiler doesn't", implying a cast when retrieving the value.

While both (any and a void pointer) will work the same way (pointer aside), if you cast to the wrong type, any will throw an bad_any_cast exception (IIRC), while with the void pointer, you'll get undefined behavior. A simple try on coliru yielded a segfault.

Upvotes: 22

sfrehse
sfrehse

Reputation: 1072

More type safe might be:

/// header #include <boost/variant.hpp>
typedef boost::variant < boost::shared_ptr < T1 >, boost::shared_ptr < T2 >, ... > VariantT;

std::vector < VariantT > container;
container.push_back ( boost::shared_ptr < T1 > ( new T1 ) ); // or boost::make_shared
container.push_back ( boost::shared_ptr < T2 > ( new T2 ) ); // or boost::make_shared

More take a look at the Boost.Variant library.

Upvotes: 27

Casey
Casey

Reputation: 42554

Just as any fundamental pointer type is convertible to void*, any shared_ptr will convert to shared_ptr<void>:

vector<shared_ptr<void>> v;
v.push_back(make_shared<int>());
v.push_back(make_shared<MyClass>());

You now have a vector of fully type-erased shared pointers. You can't do much of anything interesting with it, however: you'd have to somehow know what types are stored in what slots of the vector to convert them back:

auto intptr = static_pointer_cast<int>(v[0]);
auto myclass_ptr = static_pointer_cast<MyClass>(v[1]);

So although it is possible to do this, it's not terribly useful and probably an indication of a broken design.

Upvotes: 5

Related Questions