使用指针或引用时的模板特化优先级

时间:2010-12-08 16:43:28

标签: c++ inheritance template-specialization

我有一个像这样的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>时,程序当然会出错,这很烦人。

有什么方法吗?

3 个答案:

答案 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?

显然他们使用了一些非常精美的模板 - 魔法来让它发挥作用。我可以“轻松”自己编写类似的功能。

当你不够聪明自己解决时,请看专业人士;)