2010-12-08 26 views
2

j'ai une classe sérialiseur comme ceci:priorités de spécialisation de modèle lors de l'utilisation des pointeurs ou des références

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; 
}; 

Maintenant, mon problème est quand j'ai des classes qui héritent de l'interface Serializable ils seront toujours traitées par Func 1, même si Je veux qu'ils soient traités par Func 2 (les pointeurs ou les références n'ont pas d'importance, ils se comportent tous les deux de la même manière). Il semble que C++ ne reconnaît pas que l'interface Serializable est héritée sauf si vous spécifiez clairement que:

SerializableClass sc; // Inherits Serializable 
InputSerializer s; // Inherits Serializer 

s.Serialize(&sc); // Func 1 is called >:(
s.Serialize<Serializable>(&sc); // Func 2 is called 

Maintenant, dès que j'oublie d'ajouter <Serializable> quelque part le programme de bugs de cours sur, ce qui est assez gênant.

Y a-t-il un moyen de contourner ce problème?

+1

Cela semble être une question très similaire: http://stackoverflow.com/questions/4371699/mixing-template- fonction-overloading-and-heritage – UncleBens

+0

Vérifié dehors et oui c'est en effet la même chose. Et là, la fonctionnalité Boost était à nouveau la solution. Je suppose que je dois accepter qu'il n'y a pas de solution C++ pure à cela (il y avait une bonne explication à pourquoi cela ne fonctionnerait pas dans ce fil aussi bien). – DaedalusAlpha

+0

La solution boost ne doit contenir rien qui ne soit pas pur C++. En C++ 0x, 'type_traits' et' enable_if' font partie de la bibliothèque standard. Ce dernier est trivial pour écrire vous-même, 'is_base_of' pourrait être plus compliqué. – UncleBens

Répondre

1

Il semble que C++ ne reconnaît pas que l'interface Serializable est héritée sauf si vous spécifiez clairement que

Cela est vrai. Si vous avez une classe

class SerializableClass : public Serializable 

seulement SerializableClass, non Serializable, est considérée lorsque le paramètre déduisant T. Si vous avez besoin de créer deux fonctions, l'une prenant n'importe quel pointeur, l'autre prenant un pointeur sur tout ce qui est dérivé de Serializable, vous pouvez créer deux surcharges et utiliser SFINAE pour sélectionner le plus étroit possible.

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*) { ... } 

Si vous ne souhaitez pas utiliser boost, vous pouvez implémenter la fonctionnalité requise semblable à this.

+0

Merci, mais je n'utilise pas Boost et je ne vais pas commencer à l'utiliser juste pour ça. Donc, une solution non-Boost (si possible) serait bien. – DaedalusAlpha

+0

@DaedalusAlpha: Il est assez trivial d'écrire vos propres traits de caractères. La plupart des bibliothèques standard modernes les incluent de toute façon - elles font partie de TR1. – Puppy

+0

La question est alors; Si Boost utilise une fonctionnalité déjà disponible en C++, qu'utilise-t-il dans is_base_of?Les deux seules options raisonnables que j'ai trouvées sont une comparaison utilisant typeid() qui dépend du compilateur ou qui utilise dynamic_cast qui est lent comme un diable. Ni très bonnes solutions. – DaedalusAlpha

0

Utilisez une surcharge plutôt qu'une spécialisation de modèle!

+0

Ne fonctionne pas vraiment: http://ideone.com/VQeHG – jpalecek

+0

D'accord, je viens de l'essayer. Bonne idée cependant. – DaedalusAlpha

0

J'ai trouvé un lien expliquant comment boost::is_base_of œuvres: How does `is_base_of` work?

Apparemment, ils utilisent un peu de magie modèle-fu assez de fantaisie pour le faire fonctionner. Je peux "facilement" écrire moi-même une fonction similaire.

Lorsque vous n'êtes pas assez intelligent pour résoudre vous-même, regardez les pros;)