我已经实现了一个纯C ++ 11 Any类(基于this code),类似于boost :: any,如果直接使用,效果很好。
但是我现在需要使用它作为模板参数来为变量分配参数。看看这个:
class A {
IRecognizer<Any, Any> *_recognizer;
template <typename T1, typename T2>
A(IRecognizer<T1, T2> *x) : _recognizer(x) {
}
}
和
template<typename Symbol, typename ATNInterpreter>
class IRecognizer {
public:
virtual int getState() = 0;
};
即使我可以将每个模板参数分配给Any变量,我也不允许分配IRecognizer<T1, T2> to IRecognizer<Any, Any>
。有这个问题的解决方案吗?错误消息是:
Cannot initialize a member subobject of type 'IRecognizer<Any, Any> *'
with an lvalue of type 'IRecognizer<Token *, ParserATNSimulator *> *'
我使用Any类的原因是有一个可以用任何类引用赋值的公共类型(类似于Java的Object,但是C ++没有所有其他类派生的公共对象类型)。
这里可能采用不同的方法吗?我愿意接受建议。
答案 0 :(得分:2)
您正在尝试将IRecognizer<T1, T2> *
转换为IRecognizer<Any, Any> *
。唯一允许的指针转换是从派生类指针到基类指针(即Derived*
到Base*
)或更多 cv - 指向同一类型的指针(即Derived*
至Derived const*
)或两者兼而有之。
IRecognizer<T1,T2>
与IRecognizer<Any, Any>
不在同一个层次结构中。它们是两种不相关的类型。如果有意义的话,您可以添加构造函数将IRecognizer<A,B>
转换为IRecognizer<C,D>
,但是您无法为指针添加类似的东西。
答案 1 :(得分:1)
指向X的指针与X不同。
虽然您可以将X转换为Y(IRecognizer<T1,T2>
转换为IRecognizer<Any,Any>
),但您无法将指向X
的指针转换为指向Y
的指针。< / p>
你可能不想要指针。相反,您可能需要一个值。
但是,界面不是值。
Java泛型与C ++模板不同。 Java通用Bob<Type>
是Bob<Object>
的包装器 - 它实际上存储了一个Object
,在它上面的一层中包含了一堆包装转换。 / p>
你可以用C ++编写这样的包装器。举个例子:
class IRecognizer_base {
public:
virtual int getState() = 0;
};
template<typename Symbol, typename ATNInterpreter>
class IRecognizer:public IRecognizer_base {
};
现在,假设getState()
返回了Symbol
:
class IRecognizer_base {
public:
virtual Any getState_() = 0;
};
template<typename Symbol, typename ATNInterpreter>
class IRecognizer:public IRecognizer_base {
public:
inline Symbol getState() {
return getState_(); // whatever conversion required to go from `Any` to `Symbol`
}
};
在这里,我们揭露了我们的对象实际上返回Any
的事实,但是在接口中我们将它们转换过来。
如果您实际根据模板类型公开了实际上不同的操作,则可以键入擦除策略,以便存储可以执行这些操作的任何操作,而不是指向特定类型的指针。