我有一个像这样的Serializer类:
class Serializer
{
public:
// Func 1 (default)
template <class T>
void Serialize(T* pValue)
{
SerializeInternal(reinterpret_cast<char*>(pValue), sizeof(*pValue));
}
// Func 2 (specialization)
template <>
void Serialize<Serializable>(Serializable* pSerializable)
{
pSerializable->Serialize(*this);
}
protected:
// Implemented by input and output serializers
virtual void SerializeInternal(char* pData, size_t size) = 0;
};
现在我的问题是当我有继承Serializable接口的类时,它们将始终由Func 1处理,即使我希望它们由Func 2处理(指针或引用并不重要,它们的行为都相同)。看起来C ++没有认识到Serializable接口是继承的,除非你明确指出:
SerializableClass sc; // Inherits Serializable
InputSerializer s; // Inherits Serializer
s.Serialize(&sc); // Func 1 is called >:(
s.Serialize<Serializable>(&sc); // Func 2 is called
现在,当我忘记在某处添加<Serializable>
时,程序当然会出错,这很烦人。
有什么方法吗?
答案 0 :(得分:1)
似乎C ++没有认识到Serializable接口是继承的,除非你明确指定
这是事实。如果你有一些课
class SerializableClass : public Serializable
在推断SerializableClass
参数时,只考虑Serializable
,而不是T
。
如果您需要创建两个函数,一个采用任何指针,另一个采用指向Serializable的任何指针,您可以创建两个重载并使用SFINAE在可能的情况下选择较窄的一个。
template <class T>
typename boost::enable_if_c<!boost::is_base_of<Serializable, T>::value, void>::type foo(T*) { ... }
template <class T>
typename boost::enable_if<boost::is_base_of<Serializable, T>, void>::type foo(T*) { ... }
如果您不想使用boost,则可以实现类似于this的所需功能。
答案 1 :(得分:0)
使用重载而不是模板专门化!
答案 2 :(得分:0)
我找到了一个解释boost::is_base_of
工作原理的链接:How does `is_base_of` work?
显然他们使用了一些非常精美的模板 - 魔法来让它发挥作用。我可以“轻松”自己编写类似的功能。
当你不够聪明自己解决时,请看专业人士;)