2010-12-08 119 views
2

我有一个串行类是这样的:模板专业化优先

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>地方当然错误的程序出来,这是非常烦人。

有没有办法解决这个问题?

+1

这似乎是一个非常类似的问题:http://stackoverflow.com/questions/4371699/mixing-template-函数重载和继承 – UncleBens 2010-12-08 16:47:12

+0

检查出来,是的它确实是同样的事情。那里的Boost功能又是解决方案。我想我必须接受没有纯粹的C++解决方案(有一个很好的解释,为什么它不能在该线程中工作)。 – DaedalusAlpha 2010-12-08 17:09:27

+0

增强解决方案应该不包含任何不是纯C++的东西。在C++ 0x中,`type_traits`和`enable_if`是标准库的一部分。后者很容易写出自己,`is_base_of`可能会更棘手。 – UncleBens 2010-12-08 17:15:20

回答

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所需的功能。

0

使用重载而不是模板专门化!

0

我找到了一个链接,说明如何boost::is_base_of作品:How does `is_base_of` work?

显然,他们使用一些非常奇特的模板福魔术得到它的工作。我可以“轻松”自己编写类似的功能。

当你没有足够的智慧来自己解决问题,看看利弊;)