I have two different classes as below:
class text
{ };
class element
{ };
And I want to store them in the class node
:
template <typename T>
class node
{
T cargo;
std::vector<void*> children;
node(T cargo) : cargo(cargo)
{ };
void add_child(T node)
{
this->children.push_back((void*) node);
}
}
So I would call the node this way storing both, text
and element
's:
element div;
text msg;
node<element> wrapper(div);
wrapper.add_child(msg);
EDIT: To get back the content I use T typedef type;
and convert void pointer to (type*)
.
I know that's not very elegant nor functional, but I just can't figure out what's the correct way of doing that. So please tell me if this is practically acceptable and if it is not, how to do that in the proper manner.
Thanks in advance!
How would you get them back if you do this? From a
void*
there is no way to determine what is actually stored on the address.Edit: If you always do a cast into
T*
then you can simply takeT*
as the parameter.I would say that void* is nearly always "bad" (for some definition of bad). Certainly, there are likely to be better ways of expressing what it is you're trying to do. If it were me writing this code and I knew the types of the values I was going to put in, then I would consider using a Boost.Variant. If I didn't (for example, this was supplied as a library to someone else to "fill up"), then I would use Boost.Any
For example:
A non-boost typed union solution:
Note: you have to be a whole lot more careful about memory management with the typed union.
If your container value is limited to a small number of types, you could achieve this using
boost::variant
as shown here:I have taken the liberty of suggesting a couple of other mods - use
const
reference instead of pass-by-value onnode
constructor andadd_child
; make the containerchildren
static as I don't think it makes sense for eachnode<T>
to have its own container. Locking would be required for multithreaded usage ofadd_child
in this case. These comments apply whether you can use Boost or not in your final solution.You can perform operations on the
vector
elements using eitherget
orstatic_visitor
- the latter is preferable since you can make this generic - as shown here. An example ofvector
iteration analogous to what you would use for this solution:Output is:
First, there's no such a thing as "bad" to use a void pointer. Forget all the conventions and bla-blas, and do what's most appropriate for your case.
Now, in you specific case, if there's any connection between those two classes - you may declare a base class, so that those two will inherit it. Then, you may declare the vector of a pointer of that base class.
Cheers & hth.,
PS: Error checking, lifetime management, iteration etc. omitted in this example code.
Define a shared base class for
element
andtext
and thenadd_child
can take a pointer to the base class, and the vector can store pointers to the base class.