2009-06-02 6 views
30

Quelle est la raison pour les seconds supports <> dans le modèle de fonction suivante:Fonction Format de spécialisation de modèle

template<> void doh::operator()<>(int i) 

Cela est arrivé dans SO question où il a été suggéré qu'il y a des crochets portés disparus après operator(), mais je pouvais pas trouver l'explication.

Je comprends le sens que si elle était une spécialisation de type (spécialisation complète) de la forme:

template< typename A > struct AA {}; 
template<> struct AA<int> {};   // hope this is correct, specialize for int 

Cependant pour les modèles de fonction:

template< typename A > void f(A); 
template< typename A > void f(A*); // overload of the above for pointers 
template<> void f<int>(int);   // full specialization for int 

D'où vient cette forme dans ce scenarion ?:

template<> void doh::operator()<>(bool b) {} 

Exemple de code qui semble fonctionner et ne donne aucun rnings/erreur (gcc 3.3.3 utilisé):

#include <iostream> 
using namespace std; 

struct doh 
{ 
    void operator()(bool b) 
    { 
     cout << "operator()(bool b)" << endl; 
    } 

    template< typename T > void operator()(T t) 
    { 
     cout << "template <typename T> void operator()(T t)" << endl; 
    } 
}; 
// note can't specialize inline, have to declare outside of the class body 
template<> void doh::operator()(int i) 
{ 
    cout << "template <> void operator()(int i)" << endl; 
} 
template<> void doh::operator()(bool b) 
{ 
    cout << "template <> void operator()(bool b)" << endl; 
} 

int main() 
{ 
    doh d; 
    int i; 
    bool b; 
    d(b); 
    d(i); 
} 

Sortie:

operator()(bool b) 
template <> void operator()(int i) 
+0

La syntaxe ci-dessus de la double parenthèse est très étrange. Normalement, j'ai vu l'opérateur (bool b), mais comment fonctionne operator() (bool b)? Quelle est l'utilisation du premier vide()? – Jimm

+1

@Jimm le nom de la méthode est 'operator()' et il faut un paramètre 'bool b' ... c'est l'opérateur d'appel de fonction. Voir 'main' dans mon exemple de code,' d (b) ' – stefanB

Répondre

31

Je l'ai regardé vers le haut, et a constaté qu'il est spécifié par 14.5.2/2:

A local class shall not have member templates. Access control rules (clause 11) apply to member template names. A destructor shall not be a member template. A normal (non-template) member function with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class. When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.

Et il donne un exemple:

template <class T> struct A { 
    void f(int); 
    template <class T2> void f(T2); 
}; 

template <> void A<int>::f(int) { } // non-template member 
template <> template <> void A<int>::f<>(int) { } // template member 

int main() 
{ 
    A<char> ac; 
    ac.f(1); //non-template 
    ac.f(’c’); //template 
    ac.f<>(1); //template 
} 

Notez que dans S termes génériques, specialization fait référence à la fonction que vous écrivez en utilisant une spécialisation explicite et à la fonction générée en utilisant l'instanciation, auquel cas nous devons faire avec une spécialisation générée. specialization ne fait pas seulement référence à des fonctions que vous créez en utilisant explicitement un modèle pour lequel il est souvent utilisé. Conclusion: GCC se trompe. Comeau, avec lequel j'ai aussi testé le code, il obtient le droit et délivre un diagnostic:

"ComeauTest.c" , line 16: error: "void doh::operator()(bool)" is not an entity that can be explicitly specialized template<> void doh::operator()(bool i)

Notez qu'il ne se plaint pas de la spécialisation du modèle pour int (uniquement pour bool), car il n » t se référer au même nom et type: Le type de fonction que la spécialisation aurait est void(int), qui est distinct du type de fonction de la fonction membre non-modèle, qui est void(bool).

+0

Donc, si je suis correctement le 'membre du modèle' ci-dessus est un membre modèle dans" spécialisation de la structure A pour int ". Faites du sens maintenant, donc appeler ac.f() fera sa propre résolution de modèle basée sur le paramètre ou la liste explicite de paramètres de modèle (quel que soit le nom correct). – stefanB

+1

ouais bien la spécialisation explicite que nous avons fournie pour f est pour la spécialisation de la structure A pour int. le modèle de base général existe pour toutes les spécialisations de A.C'est pourquoi nous pouvons aussi l'appeler sur un A , comme il le fait dans main, bien sûr (mais il n'utilisera pas notre spécialisation explicite, puisque c'était seulement pour A :: f !). Ouais ac.f (truc) fait sa propre résolution, en effet. Ici, consultez 14.8.1/2 ("Les arguments du modèle final qui peuvent être déduits ..."). J'espère que cela aide :) –

+0

Oui génial, merci pour la recherche :) – stefanB

Questions connexes