If I have the following hypothetical class:
namespace System
{
template <class T>
class Container
{
public:
Container() { }
~Container() { }
}
}
If I instantiate two Containers with different T’s, say:
Container<int> a;
Container<string> b;
I would like to create vector with pointers to a and b. Since a and b are different types, normally this wouldn’t be possible. However, if I did something like:
std::stack<void*> _collection;
void *p = reinterpret_cast<void*>(&a);
void *q = reinterpret_cast<void*>(&b);
_collection.push(a);
_collection.push(b);
Then later on, I can get a and b back from _collection like so:
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
My question is, is this the best way for storing a collection of unrelated types? Also would this be the preferred way of storing and retrieving the pointers from the vector (the reinterpret cast)? I’ve looked around and seen that boost has a nicer way of solving this, Boost::Any, but since this is a learning project I am on I would like to do it myself (Also I have been curious to find a good reason to use a reinterpret_cast correctly).
While it is possible to cast to
void *and back, the problem is knowing which type you’re popping. After all, you give the example:However, if you were to accidentally do:
Now you’ve got pointers to the wrong type, and will likely see crashes – or worse.
If you want to do something like this, at least use
dynamic_castto check that you have the right types. Withdynamic_cast, you can have C++ check, at runtime (using RTTI), that your cast is safe, as long as the types being casted (both before and after) have a common base type with at least one virtual method.So, first create a common base type with a virtual destructor:
Make your containers derive from it:
Now use a
std::stack<ContainerBase *>. When you retrieve items from the stack, usedynamic_cast<Container<int> >(stack.pop())ordynamic_cast<Container<string> >(stack.pop()); if you have the types wrong, these will check, and will return NULL.That said, heterogeneous containers are almost always the wrong thing to be using; at some level you need to know what’s in the container so you can actually use it. What are you actually trying to accomplish by creating a container like this?