Hold any kind of C++ template class in member variable
I have got two classes.
The first class (A) is builded with an template.
template <class T>
class A
{
public:
T value;
};
The second class (B) should have an object of class A as member variable. L开发者_如何学Cike this:
class B
{
public:
A<int> value;
};
But now i want to use any kind of template-class in class A. Not only int. Apparent I can't declare a (member-)variable which contains any kind of a class. So, I need something like this:
class B
{
public:
A<*> value;
};
Is there any (clean) solution for this problem?
-- Greeting from Germany, Bastian
You cannot have a single class B
with "any" member object, because B
has to be a well-defined class, and A<T>
is a different type for different types T
. You can either make B
a template itself:
template <typename T>
class B
{
A<T> value;
};
or you can take a look at boost::any
, which is type-erasing container for arbitrary types (but making use of it requires a certain amount of extra work). The any
class only works for value types, though, it's not completely arbitrary.
The simplest solution would be to make all A variants ineherit from a common interface, even if it's empty :
class IA{}
template <class T>
class A : public IA
{
public:
T value;
};
class B
{
public:
IA* value;
};
Now, the associated costs:
- interactions with value are limited to the IA interface;
- if you try to cast to get the real type, that mean that you know the real type, so it's of no use and make A type a parameter of B becomes really easier to use.
- there are runtime costs associated to runtime inheritance
Advantage :
- it's easily understood by other developers
- it naturally limit the types possible to some specific ones
- it don't use boost (sometimes, you just can't)
So to do better there are other less simple solutions but that are simple enough to be used :
If you can use boost, boost::any, boost::variant and boost::mpl might be base of solutions.
Boost any can be used as a safe replacement to void*. The only problem with this is that you can have ANY type, like if the type was a template parameter of the B class.
Boost variant might be used successfully if you know all the types that A can be.
MPL might be helpful if you just want to set a list of possible types and make sure your members apply only to them. You can do a ton of things with MPL so it really depends on your exact needs.
You've got two choices, I think. The first is to parameterize your class over the type parameters of the instance variables:
template <class T> struct B
{
A<T> value;
};
The other option is to declare value
as a void*
pointer. (But that's probably not what you want).
yes, it's already been done. boost::any.
I think it helps to understand, that templated classes create an entirely new and seperate class for every type you use with it. For instance, Vector<int>
and Vector<float>
are as separate as the classes VectorInt
and VectorFloat
.
For class B, you are basically asking that the value
variable either be A<int>
or A<float>
, which is the same as saying you want value to either be a "A_int" or "A_float". And to accomplish that you... well, use another template!
精彩评论