[Gelöst] export von template Konstanten



  • Moin,

    mal wieder ein kniffeliges Unterfangen. Ich habe eine klasse definiert

    template<typename T>
    	struct Quaterniont
    	{
    		public:
    			const static Quaterniont<T> Identity;
            }
    

    und würde nun gerne darauf in einer anderen Anwendung zugreifen. Die Anwendung findet mein Quaternion ohne Probleme und kann auch darauf zugreifen.

    In der Quaternion.cpp liegt nun folgender Code

    template <typename T> const Quaterniont<T> Quaterniont<T>::Identity = Quaterniont<T>(0,0,0,1);
    

    Kompiliert alles und startet, wenn ich jetzt aber versuche zu sagen

    Quaterniont<float> q = Quaterniont<float>::Identity;
    

    Bekomme ich nach dem Start eine Fehlermeldung dass der Einstiegspunkt Identity@Quaterniont nicht gefunden wurde. Wir gehen einfach mal davon aus dass eine Export/Import-Marke mit Namen EXPORT definiert wurde.

    Was mache ich falsch bzw. wie kann ich das Problem lösen?



  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++ (auch C++0x und C++11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Du kannst Templates nicht exportieren. Sämtliche Definitionen, die von Templateparametern abhängen und in anderen Übersetzungseinheiten benutzt werden, müssen im Header stehen.



  • du meinst also aus der cpp in den header verschieben?



  • Nexus schrieb:

    Du kannst Templates nicht exportieren. Sämtliche Definitionen, die von Templateparametern abhängen und in anderen Übersetzungseinheiten benutzt werden, müssen im Header stehen.

    Seit C++11 gibt es externe Template-Definitionen. Denkbar wäre, nur Quaterniont<float> , Quaterniont<double> und Quaterniont<long double> anzubieten, dann könnte man das auch in anderen UEs definieren. Macht aber keinen Sinn.

    @Pria: Ja, so läuft das in C++. Deswegen gibt es so viele Header-only-Bibliotheken.

    Btw, was macht das "t" am Schluss, ist das ein Schreibfehler?



  • Vielleicht suggeriert das Suffix dass es ein Klassentemplate ist.



  • Pria schrieb:

    Bekomme ich nach dem Start eine Fehlermeldung dass der Einstiegspunkt Identity@Quaterniont nicht gefunden wurde. Wir gehen einfach mal davon aus dass eine Export/Import-Marke mit Namen EXPORT definiert wurde.

    die Fehlermeldung deutet darauf hin, daß DLLs verwendet werden. dabei ist zu beachten, daß für static template member in jeder DLL eigene Instanzen ereugt werden können. bei einem const member macht sich das kaum bemerkbar, man sollte aber daran denken

    http://stackoverflow.com/questions/398069/static-member-variable-in-template-with-multiple-dlls



  • moin,

    es handelt sich tatsächlich um eine dll, hätte ich villeicht erwähnen sollen, sorry.

    das t ist kein schreibfehler sondern deutet tatsächlich auf den template type T hin. Ich wollte gerne eine möglichkeit haben ohne copy/paste quaternion float, double und so weiter zu haben aber auch auf "neue" Datentypen wie half float reagieren zu können.

    Wenn ich stackoverflow-Beitrag richtig verstanden habe muss ich lediglich schreiben

    template<> struct Quaterniont<float>;
    EXPORT Quaterniont<float> Quaterniont<float>::Identity = Quaterniont<float>(0,0,0,1);
    

    und dann geht das?



  • Gibt es einen Grund, warum du die Identität nur für float definierst? Damit ist dein Template für andere Typen nur halbwegs benutzbar.



  • weil ich es erstmal für float probieren möchte, ganz einfach

    was nützt es mir es für andere datentypen zu definieren nur um hinterher dann alles samt wieder ändern zu müssen. Ausserdem verwendet man heutzutage fast ausschließlich float, obwohl OGL natürlich auch noch double und half unterstützt.



  • Ich meinte, wieso du nicht die generische Version beibehältst...



  • kann ich das denn so einfach im header definieren oder muss ich das erst spezialisieren um es exportieren zu können?



  • Also, nach etwas herumprobieren bin ich schließlich auf folgende funktionierende Lösung meines Problems gekommen:

    //im header
    
    template<typename T>
    	struct Quaterniont
    	{
    		public:
    			const static ext Quaterniont<T> Identity;
                            //dllexport ohne dllimport in der anwendung
            }
    
    template <typename T> const Quaterniont<T> Quaterniont<T>::Identity = Quaterniont<T>(0,0,0,1);
    //ohne dllexport/import
    


  • Warum eine Kopie? Du kannst doch direkt den Konstruktor nehmen.

    template <typename T>
    const Quaterniont<T> Quaterniont<T>::Identity(0,0,0,1);
    

    Was soll eigentlich ext sein? Wie gesagt, du kannst Templates nicht exportieren, alles DLL-spezifische kannst du also weglassen.



  • Weil mir der Compiler sonst eine Fehlermeldung ausspuckt, dass auf die statische Konstante nicht zugegriffen werden kann, warum auch immer es ist mir aber jetzt auch egal, es geht so und es gibt auch keine Warnungen.

    ext ist lediglich ein __dllexport ohne __dllimport.


Log in to reply