Undefined Reference bei statischer Methode / Template



  • Decimad schrieb:

    Die könnte ja in tausend Modulen instanziiert werden, mit Typen, die nur diese Module kennen...

    Ja, aber das trifft ja auf alle Templates zu, oder inwiefern sind static -Variablen hier speziell?



  • Naja, static-variablen brauchen ja einen Speicherplatz im ganzen Projekt sozusagen. Den Code für die Templates kann man ja in jedes Übersetzungseinheit basteln und darauf vertrauen, dass der Compiler in jeder Einheit kompatiblen Code erzeugt, sozusagen (da wäre also die Duplizierung nicht schlimm).



  • Also ich habe mal so ein bissl gegoogelt und dann einen Beitrag von jemandem gefunden, der aussagte, dass der Compiler im Falle von statischen Datenmembern in Klassentemplates (welche dann ja im Header auch definiert werden müssen), darauf aufpasst, dass für jede Kombination von Template-Parametern in einem Projekt nur eine Definition erzeugt wird. Da stellt sich mir die Frage, warum tut er das nicht auch bei Nicht-Template-Klassen?^^



  • Decimad schrieb:

    Da stellt sich mir die Frage, warum tut er das nicht auch bei Nicht-Template-Klassen?^^

    Wohl weil der Standard dagegen ist. Vieles wäre wahrscheinlich technisch realisierbar.

    Erlaubt C++0x nicht die Definition beliebiger statischer Member direkt innerhalb der Klasse? (Wobei das auch Nachteile hat, wenn man dadurch Abhängigkeiten in den Header verfrachtet.)



  • Passt jetzt vielleicht nicht 100% hier her, aber...: wie sieht es in C++0x mit inline initialisierten "static const" in einer Klasse aus?
    Laut dem aktuellen Standard muss man die ja nochmal ausserhalb der Klasse definieren. Was aber irgendwie keiner macht, weil es doof ist.
    Also so

    struct foo {
    	static const int c = 1234;
    };
    
    const int foo::c; // <- die Zeile die keiner schreibt, weil sie sowas von umsonst ist
    


  • Funtioniert wie gewohnt.



  • 314159265358979 schrieb:

    Funtioniert wie gewohnt.

    Sinnlose Antwort, wie gewohnt.



  • Wieder mal Löschviecher unterwegs.
    Danke!



  • Macht doch mal Bussi ihr beiden! Hilft doch nix 😉



  • Decimad schrieb:

    Macht doch mal Bussi ihr beiden! Hilft doch nix 😉

    Ich bin ruhig, solange ich nicht provoziert werde.



  • 314159265358979 schrieb:

    Wieder mal Löschviecher unterwegs.
    Danke!

    Ja, du lagst mit Deiner Antwort weit abseits.
    Du hättest analysieren sollen, inwiefern ein static const überhaupt ein Objekt ist, ob es Speicher hat, ob man damit alles machen kann, Funktionen aufrufen, Adressen oder Referenzen ziehen und so.



  • Es ging um die Initialisierung. Mehr nicht. Aber mir egal, lösch halt meine Posts, wenns dir Spaß macht.



  • OK, die Frage war vielleicht nicht ganz klar. Also nochmal.

    Der aktuelle Standard verlangt dass man integrale static const nochmal ausserhalb der Klasse definiert, auch wenn sie bereits "inline" definiert wurden. Und zwar in genau einer TU - genau so wie nicht "inline" definierte static const.

    Das nervt.

    Und daher macht es keiner (ich sehe es zumindest so-gut-wie nie).

    Die beiden grossen Compiler (GCC und MSVC) fressen das auch ohne weiteres, obwohl es laut Standard ein Fehler ist.

    Was funktioniert und was nicht ist mir daher auch einigermassen klar.

    Die Frage ist: erlaubt der neue Standard das jetzt offiziell, oder nicht?



  • If a static data member is of const literal type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

    Paragraph 9.4.2 Absatz 3

    Wenn ich das richtig gelesen habe, ist es immer noch erforderlich.



  • 314159265358979 schrieb:

    If a static data member is of const literal type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

    Paragraph 9.4.2 Absatz 3

    Wenn ich das richtig gelesen habe, ist es immer noch erforderlich.

    Ich fürchte, ich lese, daß man das member nicht in der UE definieren muß, solange man es nur als Konstante benutzt, wie in Arraygrößenangaben oder arithmetischen Ausdrücken. Also dürfen wir weitermachen wie bisher.
    Nur, wenn man es ODR-benutzt, muß man es auch noch definieren. Was ist ODR-benutzen?



  • Es tut mir leid die aktuelle Diskussion zu unterbrechen,
    aber ich bin mit der Korrektur meines Quellcodes trotz allem Genannten ein wenig überfordert.
    Kann mir jemand den korrigierten Quellcode aufschreiben?
    Vielen Dank,
    Adam S



  • Meine Lösung auf der ersten Seite, ergänzt um ein typename vor dem Rückgabetyp, vergleiche die Antwort auf meine Frage von Nexus.



  • Vielen Dank!
    Solch ein Konstrukt habe ich noch nie verwendet, ich entschuldige mich für meine Begriffsstutzigkeit.

    Es funktioniert mit folgenden Zeilen hinter der Klassendefinition.

    template <class ResourceType>
    typename ResourceManager<ResourceType>::ResourceMap ResourceManager<ResourceType>::resourcemap = ResourceManager<ResourceType>::ResourceMap();
    


  • No clockthing!

    Aber es könnte genausogut lauten:

    template <class ResourceType>
    typename ResourceManager<ResourceType>::ResourceMap ResourceManager<ResourceType>::resourcemap;
    

    Und durch die Methode des genauen hinsehens sieht man, dass es dem Muster einer normalen Variablendefinition gleichkommt, nur dass die Typen und Klassen von einem weiteren Typ abhängen.


Anmelden zum Antworten