Question

Quelle est la raison pour les deuxièmes crochets <> dans le modèle de fonction suivante:

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

Cela est arrivé dans SO question où il a été suggéré qu'il y crochets portés disparus après operator(), mais je ne 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 pas d'avertissement / erreur (3.3.3 gcc 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)
Était-ce utile?

La solution

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

  

Une classe locale ne doit pas avoir des modèles membres. règles de contrôle d'accès (article 11) sont applicables aux noms de modèle membre. Un destructor ne doit pas être un modèle de membre. Une fonction membre normale (non-matrice) avec un nom et un type et d'un modèle de fonction de membre du même nom, qui pourrait être utilisé pour générer une spécialisation du même type, peut à la fois être déclarée dans une classe. Lorsque les deux existent, une utilisation de ce nom et le type fait référence à l'élément non-modèle à moins qu'une liste explicite des arguments de modèle est fourni.

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 qu'en termes standard, specialization fait référence à la fonction que vous écrivez avec une spécialisation explicite et à la fonction générée à l'aide instanciation, dans ce cas, nous devons faire avec une spécialisation générée. specialization ne crée pas seulement aux fonctions que vous référer à l'aide d'un modèle spécialisé explicitement, pour lequel il est souvent utilisé uniquement.

Conclusion: GCC se trompe. Comeau, avec lequel j'ai aussi testé le code, il obtient le droit et délivre un diagnostic:

  

"ComeauTest.c", ligne 16: erreur: "void doh::operator()(bool)" est pas une entité qui             peut être explicitement spécialisé     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 ne se réfère pas au même nom et Type: Le type de fonction que la spécialisation serait avoir est void(int), qui est distinct du type de fonction de la fonction de membre non-modèle, qui est void(bool).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top