2012-03-25 6 views
0

Gegeben:Funktion Spezialisierung: Welche ist die Deklaration?

template<class T> 
struct test { 

    void foo(int b); 

    void testFunc(int a) 
    { 
    } 

}; 

void test::foo(int b) 
{ 

} 


template<> 
void test<float>::testFunc(int a) 
{ 

} 

void someFunction() 
{ 
} 

Wir wissen, dass "test::foo" eine Erklärung, in der Testklasse, und eine Definition außerhalb der Klassendefinition.
Wir wissen auch, dass "someFunction" eine Erklärung hat, die auch seine Definition ist.
In ähnlicher Weise "test::testFunc" (nicht spezialisiert), hat eine Erklärung, die auch seine Definition ist.
Wird die Spezialisierungsfunktion "test<float>::testFunc" mit der Deklaration von "testFunc" innerhalb der Klasse "Test" deklariert und separat definiert, oder ist deren Deklaration auch die Definition?

Antwort

3

Die explizite Spezialisierung in Ihrem Beispiel ist eine Deklaration, die auch eine Definition ist. Man könnte es auch separat deklarieren:

template<> 
void test<float>::testFunc(int a); 

und wenn die Funktion verwendet wurde, würde der Linker erwartet, dass es irgendwo definiert werden.

Die Deklaration in der Klasse ist die Deklaration und Definition der Elementfunktionsvorlage.

BTW, foo sollte wie folgt definiert werden:

template <class T> 
void test<T>::foo(int b) 
{ 

} 
1

Ich möchte die sachdienliche Antwort hinzufügen @Vaughn zur Verfügung gestellt.

In der Schablonendefinition von test haben Sie eine nicht definierende Memberfunktionsdeklaration und auch eine definierende Memberfunktionsdeklaration. Diese Funktionsdefinition und Deklaration ist jedoch mit der umgebenden Vorlage test<T> verknüpft und nicht mit der Klasse test<float>, die eventuell daraus instanziiert wird!

Wenn Sie implizit test<float> aus dieser Vorlage instanziiert, zum Beispiel durch den :: -Operator (scope) auf sie, oder durch eine Variablendefinition zu schaffen diese Art mit und so weiter, dann Erklärungen aber nicht unbedingt die Definitionen von alle Mitglieder sind auch implizit instanziiert. Alle von ihnen sind mit Mitgliedern der test<float> verbunden.

Also, wenn Sie Ihre ausdrückliche Spezialisierung für test<float>::testFunc schreiben, da Sie :: verwendet, um in der Klasse suchen test<float>, dass Klasse implizit instanziiert wird, und mit ihm alle seine Mitglieds Erklärungen.

Die Definition von test<float>::testFunc wird nur instanziiert, wenn es erforderlich ist (z. B. wenn Sie es aufrufen).

Die explizite Spezialisierung Sie dann erklärt redeclares die Member-Funktion, die zuvor implizit instanziiert wurde und eine Definition, dass mit test<float> assoziiert ist. Es ist eine echte Funktion und kann nicht sicher in einem Header definiert werden, es sei denn, es ist inline markiert - andernfalls riskieren Sie "mehr als einmal definiert" Fehler, wenn Sie seine Header mehrere Timrs enthalten.

Um zusammenzufassen, was Erklärungen und Definitionen für testFunc existieren und wo sie herkommen:

  • Durch Ihre Template-Definition:

    • test<T>::testFunc(int);
    • test<T>::testFunc(int) { }
  • generiert Spezialisierung durch den Compiler von test<T>::testFunc(int);

    • test<float>::testFunc(int);
  • Explizite Spezialisierung durch Sie test<T>::testFunc(int);

    • test<float>::testFunc(int);
    • test<float>::testFunc(int) { }

Insbesondere gibt es keine generierte Definition von test<float>::testFunc. Wenn dies der Fall wäre, wäre Ihr Code schlecht formatiert, ohne dass eine Diagnose erforderlich wäre, da die generierte Definition Ihre explizite Spezialisierung beeinträchtigen würde, die eine Definition für die gleiche Funktion lieferte. Aber so etwas kann nur passieren, wenn Sie seine Instanziierung verursachen, bevor Sie sie explizit spezialisieren. Wenn Sie also die Definition der expliziten Spezialisierung in eine .cpp-Datei verschieben (wenn Sie es nicht inline machen möchten), fügen Sie eine explizite Spezialisierung Deklaration, wie @Vaughn demonstriert, in den Header.