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?
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
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