2010-08-21 18 views
2

Ce que dit la question. En outre, est-il possible de faire cela en ligne?Comment spécialiser les fonctions membres en fonction de l'argument du modèle de classe

Voici un petit exemple juste pour donner une idée ...

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    void do(const Foo<T> &f) { 
    z = f.z; 
    } 
    // specialize 'do' for Foo<int>, possible inline? 

private: 
    T z; 
}; 
+0

AFAIK ce n'est pas possible. – Tronic

+5

Notez que votre fonction ne peut pas s'appeler 'do', puisque' do' est un mot-clé. –

+0

Oubliez les inline. Inline est un concept que nous en tant que programmeurs devrions ignorer et laisser aux dieux informatiques suprêmes (AKA comme compilateurs) –

Répondre

3

Vous pouvez obtenir sorte de ce comportement en faisant la fonction de membre d'un modèle de fonction membre et en utilisant SFINAE (échec de substitution n'est pas une erreur). Par exemple:

template <typename U> 
typename std::enable_if<!std::is_integral<U>::value && 
         std::is_same<T, U>::value, void>::type 
f(const Foo<U>& x) 
{ 
} 

template <typename U> 
typename std::enable_if<std::is_integral<U>::value && 
         std::is_same<T, U>::value, void>::type 
f(const Foo<U>& x) 
{ 
} 

Le test de trait de type is_integral si U est un type entier. Si ce n'est pas le cas, le premier est instancié; si c'est le cas, la seconde est instanciée.

Les tests de caractéristiques de type is_same pour assurer T et U sont du même type. Ceci est utilisé pour s'assurer que le modèle de fonction membre n'est instancié pour aucun type autre que Foo<T>.

Cet exemple utilise la bibliothèque C++ 0x <type_traits>; Boost a également a type traits library que vous pouvez utiliser, qui fonctionne la plupart du temps la même chose.

+0

Merci! Je dois dire cependant, si la syntaxe est comme ça, je vais probablement aller avec mes alternatives. – floogads

+0

Je ne vois pas std :: enable_if. On dirait que cela ne fait pas partie de la norme. – Brent

+0

@Brent: C'est. C'est défini dans ''. –

-1

Vous pouvez essayer de faire quelque chose comme ça (ne pas tester, pourrait ne pas fonctionner):

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    template<typename Ty = T> 
    void do(const Foo<T> &f) { 
    z = f.z; 
    } 

    template<> 
    void do<int>(const Foo<T> &f) { 
    //specialized code 
    } 

private: 
    T z; 
}; 
+0

Une spécialisation n'est pas nécessaire et cela peut être accompli en utilisant une surcharge. Le problème avec la surcharge est que vous devrez surcharger la fonction membre pour chacun des types intégraux. Il pourrait y avoir jusqu'à douze types intégraux (ou plus, j'ai perdu la trace peu de temps après que j'ai manqué de doigts), ce qui est beaucoup de surcharges à avoir à écrire. –

+2

En fait, ça ne marche pas comme ça. Je ne comprendrai jamais pourquoi les gens postent du code qu'ils ne connaissent pas est valide. Le questionneur peut faire beaucoup aussi. –

+0

Il y a 2 problèmes avec ceci: Vous ne pouvez pas spécialiser les modèles de membres en ligne et vous ne pouvez pas les spécialiser sans entièrement spécialiser la classe contenant. –

3

Vous n'avez pas besoin de faire quoi que ce soit compliqué. Utilisez simplement la surcharge et la délégation. Notez que nous ne pouvons pas simplement ajouter une surcharge int, parce que quand T se révèle être int aussi, ce serait une surcharge invalide (deux fonctions avec la même signature)

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    void doIt(const Foo<T> &f) { 
    doItImpl(f); 
    } 

private: 
    template<typename U> 
    void doItImpl(const Foo<U> &f) { 
    z = f.z; 
    } 

    void doItImpl(const Foo<int> &f) { 
    /* ... */ 
    } 

private: 
    T z; 
}; 

Ou, pour ce cas, vous pouvez le faire ceci par spécialisation

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    void doIt(const Foo<T> &f) { 
    z = f.z; 
    } 

private: 
    T z; 
}; 

template<> 
inline void Foo<int>::doIt(const Foo<int> &f) { 
    /* ... */ 
} 

L'utilisation de la spécialisation de cette manière n'est possible que si tous les arguments du modèle sont corrigés. En d'autres termes, la spécialisation partielle de la fonction membre n'est pas possible.