2014-01-14 2 views
11

Der folgende Code nicht auf gcc 4.5.3Spezialisierung der Mitgliedsfunktionsvorlage nach der Instanzierung Fehler, und die Reihenfolge der Elementfunktionen

struct Frobnigator 
{ 
    template<typename T> 
    void foo(); 

    template<typename T> 
    void bar(); 
}; 

template<typename T> 
void Frobnigator::bar() 
{ 
} 

template<typename T> 
void Frobnigator::foo() 
{ 
    bar<T>(); 
} 

template<>  // error 
void Frobnigator::foo<bool>() 
{ 
    bar<bool>(); 
} 

template<> 
void Frobnigator::bar<bool>() 
{ 
} 

int main() 
{ 
} 

Fehlermeldung zu kompilieren: specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation. Ich löste dieses Problem schließlich, indem ich die Spezialisierung Frobnigator::bar<bool>() vor Frobnigator::foo<bool>() erscheinen ließ. Offensichtlich ist die Reihenfolge, in der die Methoden erscheinen, von Bedeutung.

Warum dann ist die folgende Lite-Version des obigen Codes, in dem die Spezialisierung von bar nach der generischen Version erscheint, gültig?

struct Frobnigator 
{ 
    template<typename T> 
    void foo(); 
}; 

template<typename T> 
void Frobnigator::bar() 
{ 
} 

template<> 
void Frobnigator::bar<bool>() 
{ 
} 

int main() 
{ 
} 

Antwort

18

Ihr erster Code ist standardmäßig nicht korrekt.

n3376 14.7.3/6

Wenn eine Vorlage, ein Mitglied Vorlage oder ein Mitglied einer Klasse-Vorlage wird explizit spezialisiert dann, dass Spezialisierung wird vor der ersten Verwendung dieser Spezialisierung erklärt werden, die eine implizite verursachen würde Instanziierung stattfinden, in jeder Übersetzungseinheit, in der eine solche Verwendung auftritt; keine Diagnose ist erforderlich.

In Ihrem Fall - implizite Instanziierung bar Funktion mit Typ bool zeichnet sich durch seine Verwendung in foo<bool>, bevor expliziter Spezialisierung Erklärung erforderlich.

2

Offensichtlich die Reihenfolge, in der die Methoden erscheinen.

In der Tat; Wie in C++ üblich, können Sie vor der Deklaration nichts verwenden. Dies gilt sowohl für explizite Vorlagenspezialisierungen als auch für die meisten anderen Dinge.

Die Verwendung von bar<bool> (durch Aufruf von foo<bool>) ohne vorherige Deklaration einer expliziten Spezialisierung bewirkt, dass die Spezialisierung aus der generischen Vorlage instanziiert wird, falls dies nicht bereits geschehen ist. Um dies zu verhindern, benötigen Sie mindestens eine explizite Erklärung der Spezialisierung.

Warum ist dies der Fall, wenn man bedenkt, dass die Spezialisierung der Bar nach der generischen Version in der folgenden Lite-Version des obigen Code erscheint

Das zweite Beispiel unterscheidet sich von nicht foo<bool> gar Instanziierung. Das Problem ist nicht, dass die Spezialisierung nach der generischen Vorlage deklariert wird (was der Fall sein muss), sondern dass sie deklariert wird, nachdem diese Spezialisierung bereits instanziiert wurde.