C ++ defining type of member class without template argument

I am trying to set the type of a member of a class without passing it through a template argument.

More details:

// Forward declaration: class A; class B; class Base { }; template <class T> class Derived : public Base { private: T2 var; }; 

where T can be either class A or class B What I would like to do is for Derived<A> T2 - int (for example), and for Derived<B> T2 - double (for example). I would like to avoid the following solution:

 template <class T1, class T2> class Derived : public Base { private: T2 var; }; 

I want to avoid this, because for Derived<A> can be various possible combinations for T2: Derived<A,int> , Derived<A,double> , ...

I want the T2 type to be unique to all Derived<A> .

Any ideas how to solve this?

+6
source share
3 answers

Update:. The comments show that the original problem you are trying to solve is not fully explained in the question. I will leave the original answer, however, at the bottom of this answer.

You cannot have two Derived<A> with different T2 types for the var member. In addition, a user-defined variable cannot affect the type of a member variable . Variable values ​​are set at runtime, types are defined in compiletime.

To save a user-defined type, you will either have to limit the variable to a set of known types, or use a single type containing a serialized version of the variable's contents. A set of well-known types is often used in the context of databases, where fields can have one of several predefined types (for example, String, Integer, Boolean, Double). The type of the member variable can then be Boost.Variant, limited to C ++ representations of this type. Another application, "user-defined types", is where the user of your program must somehow determine the layout and interpretation of the type and its object, for example, if your program is an interpreter of some scripting language. In this case, Boost.Variant (or something similar) may be useful again, or, since the value is probably some user input, just store the serialized value in a string and interpret it every time you have to deal with it .

Original answer:

Usually this is done using metaprogramming of templates, in this case a function of the type (sometimes, depending on the context, part of the attributes, or policy class):

 template <class T> struct DerivedMemVarType { typedef double type; //default }; template<> struct DerivedMemVarType<A> { typedef int type; }; 

And then:

 template <class T> class Derived : public Base { typedef typename DerivedMemVarType<T>::type T2; private: T2 var; }; 

You can also leave the default value, so any creation of Derived for a type that you did not display in your function will give a compilation error:

 template <class T> struct DerivedMemVarType; //default is not defined template<> struct DerivedMemVarType<A> { typedef int type; }; template<> struct DerivedMemVarType<B> { typedef double type; }; //... Derived<C> dc; // ...template error mess.... // --> error: invalid use of incomplete type 'struct DerivedMemVarType<C>' 
+7
source

if you don’t have a special function call, you can use something like ...

 class A; class B; class Base { }; template <class T> class Derived : public Base { public: Derived(T startVal):var(startVal){} private: T var; }; template <typename T> Derived<T> MakeDerived(T initValue) { return Derived<T>(initValue); } 

and now you can use its following, and the compiler should know what type you are passing to the function.

 int initialValue = 0; auto derived = MakeDerived(initialValue); 
0
source

I think you can create a separate class that simply contains a typedef, which you then specialize and use in your Derived class.

 template<typename T> class VarType { public: typedef int TheType; } template <> class VarType<B> { public: typedef double TheType; }; template <typename T> class Derived : public Base { private: typename VarType<T>::TheType var; }; 
0
source

All Articles