我正在尝试设置类成员的类型,而不通过模板参数传递它。
详情:
// Forward declaration:
class A;
class B;
class Base
{
};
template <class T>
class Derived : public Base
{
private:
T2 var;
};
其中T可以是class A
或class B
。
我想要做的是Derived<A>
T2是int(例如),而Derived<B>
T2是double(例如)。我想避免以下解决方案:
template <class T1, class T2>
class Derived : public Base
{
private:
T2 var;
};
我想避免这种情况,因为对于Derived<A>
,T2可能有各种可能的组合:Derived<A,int>
,Derived<A,double>
,...
我想要的是T2的类型对于整个Derived<A>
是唯一的。
知道如何解决这个问题吗?
答案 0 :(得分:7)
更新:评论显示您尝试解决的原始问题未在问题中完整解释。不过,我会在原来的答案中留下这个答案的底部。
Derived<A>
成员不能有两个var
类型为T2的template <class T>
struct DerivedMemVarType {
typedef double type; //default
};
template<>
struct DerivedMemVarType<A> {
typedef int type;
};
。此外,用户定义的变量不能影响成员变量的类型。变量值在运行时设置,类型在编译时确定。
要以某种方式存储由用户定义的类型,您必须将变量限制为一组已知类型,或者使用包含变量内容的序列化版本的一种类型。已知类型的集合通常在数据库的上下文中使用,其中字段可以具有若干预定义类型之一(例如,String,Integer,Boolean,Double)。然后,成员变量的类型可以是Boost.Variant,仅限于该类型的C ++表示。 “用户定义类型”的另一个应用是程序用户必须以某种方式定义类型及其对象的布局和解释,例如,如果您的程序是某种脚本语言的解释器。在这种情况下,可以使用Boost.Variant(或类似的东西),或者,由于该值可能是一些用户提供的输入,只需将序列化值存储在字符串中,并在每次处理它时对其进行解释。
这通常通过模板元编程来完成,在这种情况下是一个类型函数(有时,取决于上下文,特征或策略类的一部分):
template <class T>
class Derived : public Base
{
typedef typename DerivedMemVarType<T>::type T2;
private:
T2 var;
};
然后:
Derived
您也可以省略默认值,这样对于您未在函数中映射的类型的任何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>'
实例化都会产生编译错误:
{{1}}
答案 1 :(得分:0)
如果您没有任何特定类型的函数调用,则可以使用类似......
的内容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);
}
现在您可以使用以下内容,编译器应该知道您传递给函数的类型。
int initialValue = 0;
auto derived = MakeDerived(initialValue);
答案 2 :(得分:0)
我认为你可以创建一个单独的类,它只包含一个typedef,然后你可以在Derived类中专门使用它。
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;
};