2016-11-10 5 views
2

Ich habe eine Klassenvorlage mit einem statischen const-Element erstellt. Die Absicht ist, dass jede Spezialisierung der Vorlage ihre eigene Version/Wert dieses statischen Elements hat. Hier ist mein Beispielcode:Initialisierung eines statischen const für eine Template-Spezialisierung

template < typename T > class C 
{ 
    public: 
     static const std::string NAME; 
     T something; 
     void printName() { std::cout << NAME << std::endl; } 
}; 

class C1 : public C<int>{}; 
class C2 : public C<char>{}; 

template<> const std::string C<int>::NAME{ "my int" }; // compiles 
template<> const std::string C<char>::NAME{ "my char" }; // compiles 

//template<> const std::string C1::NAME{ "my int" }; // doesn't compile 
//template<> const std::string C2::NAME{ "my char" }; // doesn't compile 

//const std::string C1::NAME{ "my int" }; // doesn't compile 
//const std::string C2::NAME{ "my char" }; // doesn't compile 

int main() 
{ 
    C1 c1; 
    C2 c2; 

    c1.printName(); 
    c2.printName(); 

    std::cout << c1.NAME << " " << c2.NAME << std::endl; 
    std::cout << C1::NAME << " " << C2::NAME << std::endl; 
} 

Wenn die übersetzbare Version verwendet wird, ist der Ausgang, was ich erwarten würde:

my int 
my char 
my int my char 
my int my char 

Für die Linien, die kompilieren nicht, die Fehlermeldung (mit gcc 4.4) sagt

ISO C++ does not permit 'C<int>::NAME' to be defined as 'C1::NAME' 

Warum ist das nicht erlaubt? Nach meinem Verständnis ist eine vollständige Spezialisierung einer Vorlage eine Klasse in allen (?) Aspekten, und diese Klasse enthält alle in der Vorlage deklarierten Elemente. Ich würde also erwarten, dass ich mit einem Scope-Resolution-Operator auf statische Member dieser Klasse verweisen kann. Offenbar kann ich das nach der Initialisierung tun, wie in der letzten Zeile von main, aber nicht in der Initialisierung selbst.

Kann jemand einen Einblick geben, warum der Standard auf diese Weise geschrieben wurde? Welche Art von Problemen würde auftreten, wenn der Standard die obige "schlechte" Syntax zulässt?

Antwort

3

Es sieht für mich so aus, als ob das Problem, mit dem Sie konfrontiert sind, nichts mit Vorlagen zu tun hat. Das Problem besteht darin, dass Sie versuchen, ein statisches Member zu definieren, das eine abgeleitete Klasse in dem geschachtelten Name-specifier nicht der ursprünglichen Klasse verwendet. Sie würden das gleiche Problem hier haben:

struct A { 
    static int x; 
}; 
struct B : A{}; 
int B::x = 42; 

Die C1 und C2 im Code sind nicht voll Spezialisierungen von C, sondern sie sind abgeleitete Klassen von Spezialisierungen von C. Also ich weiß nicht, was Sie hier erwarten ...

+0

Das macht die Dinge klarer. Ich bin neu in Templates und versuche immer noch Konzepte wie Instanziierung vs Spezialisierung auszusortieren, und wie man sie mit Vererbung usw. kombiniert. Mal sehen, ob ich das jetzt richtig habe: So wie ich Klasse C1 deklariert habe, erzeugt der Compiler ein (implizite Instanziierung von C , die die Basisklasse für C1 sein wird. Das statische Member gehört zur Basisklasse, daher muss ich den Basisklassennamen "C " verwenden, um es zu initialisieren. Ebenso für C2 & C . C und C haben keine Vererbungsbeziehung; Sie werden nur aus derselben Vorlage generiert. Ist das in Ordnung? – user3065699

+0

Was ich erwarte, ich möchte, dass C1 und C2 (oder genauer gesagt ihre jeweiligen Basisklassen) jeweils ein statisches Member namens NAME mit unterschiedlichen Werten für jede (Basis-) Klasse haben. Das ist es, was ich erreicht habe; Ich war mir nicht ganz sicher, wie es funktioniert hat. – user3065699

Verwandte Themen