Frage

Was ist der Grund für die zweiten Klammern <> in der folgenden Funktionsvorlage:

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

Das kam in SO Frage wo es wurde vorgeschlagen, dass es Klammern nach operator() fehlen, aber ich konnte nicht die Erklärung finden.

Ich verstehe die Bedeutung, wenn es sich um eine Art Spezialisierung (Voll Spezialisierung) der Form war:

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

Jedoch für Funktionsschablonen:

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

Wo passt das in diesem scenarion:

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

Beispiel-Code, der scheint zu funktionieren und gibt keine Warnungen / Fehler (gcc 3.3.3 verwendet):

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

Ausgabe:

operator()(bool b)
template <> void operator()(int i)
War es hilfreich?

Lösung

Ich sah es schon auf, und stellte fest, dass es durch 14.5.2 / 2 angegeben wird:

  

Eine lokale Klasse darf nicht Mitglied Vorlagen hat. Zugriffskontrollregeln (Ziffer 11) gelten Mitglied Vorlagennamen. Ein destructor ist kein Mitglied Vorlage sein. Eine normale (Nicht-Template) Mitgliedsfunktion mit einem bestimmten Namen und den Typ und eine Elementfunktion Vorlage mit dem gleichen Namen, die verwendet werden könnten, eine Spezialisierung des gleichen Typs zu erzeugen, kann sowohl in einer Klasse deklariert werden. Wenn beide vorhanden sind, bezieht sich eine Verwendung dieser Bezeichnung und Typ der Nicht-Template-Element, sofern nicht eine explizite Template-Argumentliste geliefert wird.

Und es gibt ein Beispiel:

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
}

Beachten Sie, dass in Standardbedingungen, specialization auf die Funktion verweist mit einer expliziten Spezialisierung schreiben und auf die Funktion Instantiierung erzeugt, wobei wir mit einem generierten Spezialisierung zu tun haben. specialization nicht nur auf Funktionen beziehen Sie explizit spezialisiert, mit Hilfe einer Vorlage erstellen, für die sie oft nur verwendet.

Fazit: GCC wird es falsch. Comeau, mit dem ich auch den Code getestet, macht es richtig und gibt eine Diagnose:

  

"ComeauTest.c", Zeile 16: error: "void doh::operator()(bool)" ist nicht ein Unternehmen, das             werden kann explizit spezialisiert     template<> void doh::operator()(bool i)

Beachten Sie, dass es nicht über die Spezialisierung der Vorlage für int beschwert (nur für bool), da sie den gleichen Namen bezieht sich nicht und Typ: Der Funktionstyp, dass die Spezialisierung würde habe, ist void(int), die aus dem Funktionstyp der nicht-Template-Elementfunktion, die void(bool) ist verschieden ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top