Definition von static Elementen bei template-Klasse



  • Hallo,

    ich habe ein Klassentemplate geschrieben. Dieses enthält auch eine statische Variable, die vom template-Parameter abhängt.
    Jetzt weiß ich nicht so recht, wo ich dessen Definition unterbringen soll/muß.

    Wenn ich ihn in eine eigene cpp-Datei setze, dann steht die Definition bei der template Instanziierung nicht zur Verfügung und ich bekomme eine unresolved external reference.
    Wenn ich die Definition aber in den template-Header mit reinschreibe, dann kann ich den ja nicht in verschiedene Übersetzungseinheiten includen, weil ich sonst ne ODR-Verletzung bekomme.

    Was ist die Lösung zu diesem Dilemma?
    Vielen Dank schonmal im Voraus

    Jester



  • Hab's jetzt mal in den Header mit reingeschrieben. Merkwürdigerweise funktioniert das...
    Also neue Frage: Warum?
    Oder genauer: Warum schlägt die ODR hier nicht zu?



  • Weil dein Template sowieso keine "richtige" Klassendefinition ist (das heisst, es belegt keinen Speicher und theoretisch erzeugt es nicht ein Byte Code). Eher ein Bauplan, nach dem sich der Compiler selber die Klassen zusammenstellt.
    Ich kann mich auch täuschen, aber ich glaube für Klassen-Templates gibt es diese Sonderregel. Der Compiler muss ja für die Variable keinen Speicher bereitstellen sondern nur die Definition zur Kenntnis nehmen und bei Benutzung die Klassen erzeugen.



  • Hab's jetzt mal in den Header mit reingeschrieben. Merkwürdigerweise funktioniert das...
    Also neue Frage: Warum?
    Oder genauer: Warum schlägt die ODR hier nicht zu?

    Aus dem gleichen Grund, warum
    template<class T> void f(T t) {...}
    auch kein Problem ist. Es handelt sich lediglich um eine Schablone, aus der die echten Funktionen generiert werden, und falls f<int> mehrfach entsteht, muß der C++-Compiler dafür sorgen, dass es zu keinen Problemen kommt. dito für
    template<class T> void MyClass<T>::methode() {...} // statisch oder nicht statisch
    und
    template<class T> int MyClass<T>::var = 0; // statisch

    Grüße
    Fux



  • @Optimizer:

    Danke, ich weiß was ein template ist.

    @Fux:
    Danke für die Erklärung.



  • Hast du jetzt falsch aufgefasst. Ich hab im Grunde das selbe gesagt, nämlich, dass Template-Klassen keinen Speicher belegen und dass der Compiler sich selber die Klasse erstellt.



  • Optimizer schrieb:

    Hast du jetzt falsch aufgefasst. Ich hab im Grunde das selbe gesagt, nämlich, dass Template-Klassen keinen Speicher belegen und dass der Compiler sich selber die Klasse erstellt.

    Das hat strenggenommen aber nichts mit der Frage zu tun. Der Punkt ist hier die ODR und die Tatsache, dass alle Templatedefinition in C++ dem "once per translation unit"-Constraint unterliegen und nicht dem strengeren "once per program" dem die meisten Definitionen gehorchen müssen (z.B. die Definitionen normaler nicht inline Funktionen).



  • Genau das wollte ich wissen.



  • @Optimizer:

    Um das (gelöste) Problem nochmal klarer darzustellen:

    // gehört in den Header
    class X
    {
      static int y;
    };
    
    // gehört in die Implementierungsdatei, sonst Verletzung der ODR
    int X::y;
    

    Jetzt schreibe ich ein template:

    // in den Header
    template <typename T>
    class X
    {
      static T y;
    };
    
    // wohin damit?
    template <typename T>
    T X<T>::y;
    

    Wenn ich das in die Implementierung schreibe, dann steht es zum Zeitpunkt der Instanziierung nicht zur Verfügung, wird also nicht mitinstanziiert -> Linker-Error.

    Meine Vorstellung war jetzt aber so:
    schreibe ich X<int>, dann wird quasi der Code dafür erzeugt und bei mir in die ÜE eingefügt. Dann hätte ich aber genau die ODR-Verletzung.

    Aber bei templates ist das halt anders definiert, die Definition darf nämlich einmal pro Übersetzungseinheit die es benutzt stehen und damit ist das Problem behoben.

    MfG Jester



  • Genau. Und warum darf man Variablen nicht mehrmals definieren? Weil bei jeder Definition neuer Speicherplatz reserviert werden würde. Das gilt für Templates freilich nicht, da Templates keinen Speicherplatz beanspruchen, sondern erst die vom Compiler definierten Klassen.

    Optimizer schrieb:

    Ich kann mich auch täuschen, aber ich glaube für Klassen-Templates gibt es diese Sonderregel. Der Compiler muss ja für die Variable keinen Speicher bereitstellen sondern nur die Definition zur Kenntnis nehmen und bei Benutzung die Klassen erzeugen.

    Aber egal, das ist jetzt Haarspalterei. 🙂
    Zumindest muss ich zugeben, dass ich auch nicht sofort gewusst hätte, wie man das Problem löst.



  • Optimizer schrieb:

    Genau. Und warum darf man Variablen nicht mehrmals definieren? Weil bei jeder Definition neuer Speicherplatz reserviert werden würde. Das gilt für Templates freilich nicht, da Templates keinen Speicherplatz beanspruchen, sondern erst die vom Compiler definierten Klassen.

    Genau darum geht es aber nicht, sondern darum, ob diese vom Compiler generierten Klassen der strengen ODR genügen müssen oder nicht. Das andere war mir auch vorher schon klar.


Anmelden zum Antworten