2010-09-18 5 views
2

je le morceau de code suivant:spécialisation de la fonction de modèle pour l'interface spécifique

class ICookable 
{ 
public: 
    virtual void CookMe() = 0; 
    virtual ~ICookable() {}; 
}; 

class Egg : public ICookable 
{ 
public: 
    virtual void CookMe() {cout << "Egg cooked!" << endl;} 
}; 

template <class T> 
void Cook (T&) 
{ 
    cout << "Item Uncookable!" << endl; 
} 

template <> 
void Cook (ICookable& c) 
{ 
    c.CookMe(); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Egg egg; 
    Cook (egg); 
    return 0; 
} 

Je veux la fonction Cook se comporte différemment selon que son paramètre est héritée de l'interface ICookable ou non. Cependant, dans l'exemple ci-dessus, je reçois un message « Item Uncookable » pour le paramètre Egg, à moins que j'écris manuellement:

Cook<ICookable> (egg); 

est-il un moyen de laisser le compilateur choisir automatiquement la bonne réalisation pour les descendants ICookable?

+0

Il y a quelque chose de terriblement mal avec ce code, et je ne peux pas le trouver. Même si vous surchargez cook pour ICookable, qui devrait être sélectionné à chaque fois, cela ne fonctionne pas. – Puppy

+0

@DeadMG: Pourquoi devrait-il être sélectionné à chaque fois? La lecture "pour certains j argument, ICSj (F1) est une meilleure séquence de conversion de ICSj (F2), ou, sinon que" [13.3.3/1, 0x FCD] -qui remplace le plus tard « F1 est un non- modèle et F2 est une spécialisation de modèle de fonction "- me dit autrement. (Mais je reconnais volontiers la résolution de surcharge est horriblement complexe et je peux très bien me tromper.) –

+0

S'il vous plaît s'il vous plaît s'il vous plaît faire un réflexe d'ajouter un destructor virtuel 'ICookable'. Cela me fait mal aux yeux (et devrait blesser le vôtre). –

Répondre

3

envoi Compile temps par boost::is_base_of et modèle de classe spécialisation partielle:

template<class T, class _> 
struct CookDetail { 
    static void cook(T& obj) { 
    cout << "uncookable\n"; 
    } 
}; 
template<class T> 
struct CookDetail<T, boost::true_type> { 
    static void cook(ICookable& obj) { 
    obj.CookMe(); 
    } 
}; 

template<class T> 
void cook(T& obj) { 
    return CookDetail<T, boost::is_base_of<ICookable, T> >::cook(obj); 
} 

Cependant, après avoir cuisinier (non_icookable_obj) "travail" est une erreur pour moi. Je préférerais l'erreur de compilation pour essayer de cuisiner un non-cuisinable.

Notez que ce que vous avez essayé échoue parce que c'est tout simplement la façon dont fonctionne la résolution de la fonction. Une correspondance exacte grâce à un modèle (cuire < Egg> (Egg &)) est considéré comme meilleur que celui qui exige une conversion (cuisine (ICookable &)). Les détails sont dans le FCD si vous voulez les techniques archaïques.

Questions connexes