2010-12-08 111 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?

顯然,他們使用一些非常奇特的模板福魔術得到它的工作。我可以「輕鬆」自己編寫類似的功能。

當你沒有足夠的智慧來自己解決問題,看看利弊;)