Reputation:
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
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
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
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