Templates mit VS .net 2003



  • Hallo Leute,
    ich habe folgendes Problem mit VS.net 2003. Wenn ich eine Klasse mit einem Template definiere wird allem Anschein nach die .cpp Datei zur Klasse ignoriert bzw. nicht mitübersetzt. Beispiel:

    .h Datei:

    template<class T> class Beispiel
    {
        public:
            Beispiel(void);
    }
    

    .cpp Datei:

    #include "Beispiel.h"
    
    template <class T> Beispiel<T>::Beispiel(void)
    {
        //machwas
    }
    

    Wenn ich es so anstelle, bekomme ich beim Aufruf des Konstruktors eine unaufgelöste externe Referenz. Wenn ich den Code aus der .cpp Datei in die .h Datei kopiere - hinter die schließende Klammer der Klasse - wird alles Fehlerfrei übersetzt und ausgeführt. Hatte jemand schon mal ein ähnliches Problem oder hat jemand eine Idee, woran es liegen könnte? Ach ja, ist nur bei Klassen mit templates so, "normale" Klassen lassen sich ohne Probleme in eine .cpp und eine .h Datei aufteilen.

    Danke im voraus



  • Templatedefinitionen müssen mit in der h-Datei stehen. Templates können ja erst angelegt werden, wenn sie vom Nutzer mit einem bestimmtem Typ angelegt werden.



  • Versteh ich jetzt nicht ganz, der Code wird doch übersetzt und dann ist von .h und .cpp Dateien sowieso nichts mehr übrig. Außerdem:
    Habs mit VS 2005 probiert, wird ohne Probleme übersetzt. Demnach ist es ein Problem von VS .net 2003.
    Auch Methoden, die sich nicht auf den Typen des Templates beziehen, z.B.

    int Beispiel::getCount()
    {
     //...
    }
    

    lösen eine unaufgelöste externe Referenz aus, und das kann ja wohl irgendwie nicht sein. Das Problem ist, dass ich eine dll bzw. eine .lib übersetzen möchte und nicht will, dass alees in der .h steht - dann könnt ich das mit der Bibliothek auch gleich sein lassen.



  • Ja, das ist ein bekanntes Problem von VS6-VS.net 2003



  • Beim Umgang mit Templates muß der Compiler bei der Instanziierung (d.h. in deinem Hauptprogramm) den Quellcode der Funktionen kennen, um den richtigen Code zu erzeugen (auch wenn's nur Kleinigkeiten sein dürften - Beispiel<int>::Beispiel() sieht im fertigen Programm anders aus als Beispielstd::string::Beispiel()). Wenn du nur die Template-Datei übersetzt, weiß der Compiler ja nicht, ob er später den Code für Beispiel<int>, Beispielstd::string oder Beispiel<dummy_class> benötigen wird, deshalb kann er an dieser Stelle nichts bereitstellen.

    Und darum kommst du nicht drum herum, deinen Quellcode in den Header zu packen (außer - du packst die Funktionen in eine ".inc"-Datei, die du am Ende des Headers includest).

    PS: Und in einer Template-Klasse beziehen sich afaik ALLE Methoden (irgendwo) auf den Typ des Templates - auch wenn man ihnen das auf den ersten Blick nicht ansieht.



  • Hört sich soweit ganz vernünftig an. Aber ich kann ja auch erst zur Laufzeit entscheiden, wie ich die Klasse instanziere (Als Beispiel bei einer ausfühtbaren datei). Dann müsste doch der Compiler das Template entweder alle Möglichkeiten (also im Prinzip für alle bekannten Typen und Klassen) übersetzen, garnicht überstzen und meckern oder es doch irgendwie gebacken bekommen, die Klasse als Template zu übersetzen, das zur Laufzeit mit einem beliebigen Typen initialisiert werden kann.
    Ach ja, mit VS 2005 funktioniert es auch nicht so richtig - mein Fehler.



  • Herb schrieb:

    Hört sich soweit ganz vernünftig an. Aber ich kann ja auch erst zur Laufzeit entscheiden, wie ich die Klasse instanziere (Als Beispiel bei einer ausfühtbaren datei).

    Nö, Instanziierungen von Templateklassen und -funktionen stehen zur Compilezeit fest.

    Dann müsste doch der Compiler das Template entweder alle Möglichkeiten (also im Prinzip für alle bekannten Typen und Klassen) übersetzen,

    Und wieviel sind das? Na? Genau.

    garnicht überstzen und meckern oder es doch irgendwie gebacken bekommen, die Klasse als Template zu übersetzen, das zur Laufzeit mit einem beliebigen Typen initialisiert werden kann.

    Wie gesagt, der Compiler übersetzt Templates für genau die Typen, die zur Compilezeit angegeben sind. Und er braucht dazu den Quellcode des Templates.



  • Klar, hast natürlich recht. Darauf weist im nachhinein gesehen auch der Linker Fehler hin.
    Was ich trotzdem nicht verstehe ist das Verhalten, das VS an dieser Stelle an den Tag legt. Wenn ich mit dem Assistenten eine Methode hinzufüge, landet die Definition in der .cpp.
    Wenn ich eine Bibliothek übersetze, ist schon klar dass die .h dann in dem Projekt, in dem ich die Bibliothek verwende, allein nicht ausreicht, weil einfach keine Definitionen da sind.
    Wenn ich aber eine .exe übersetze dann sind doch alle Definitionen da, da ist es doch völlig egal wo sie stehen, VS sollte sie eigentlich finden. Das Problem ist, dass VS die .cpp Datei völlig ignoriert - da kann der totäle Müll drin stehen, interessiert nicht weiter, und das sollte eigentlich nicht sein, die Datei gehört schließlich zum Projekt.

    Danke für die Antworten, hat mir sehr weitergeholfen.



  • Wenn ich aber eine .exe übersetze dann sind doch alle Definitionen da, da ist es doch völlig egal wo sie stehen, VS sollte sie eigentlich finden.

    Falsch... 😃 Man benötigt um eine Bibliothek verwenden zu können die Header-Dateien und die Lib-Datei. Da wird nicht mehr mit den Cpp-Dateien der Bibliothek rumhantiert. Ansonsten müßte jeder der eine Bibliothek schreibt auch den Quellcode offenlegen anstelle nur die Header-Dateien der Schnittstelle....



  • Da hast Du mich jetzt irgendwie falsch verstanden. In der Diskussion oben ging es ja gerade darum, dass der Code für eine template-Klasse eben nicht in der Lib stehen kann, sondern in der .h Datei. (Da sonst, wenn mit der Lib gearbeitet wird, keine entsprechende Template Klasse erzeugt werden kann).
    Mir gings darum:
    Wenn ich eine exe erstelle, ohne Verwendung von irgendwelchen libs, dann sollte es doch völlig egal sein, wo die definition für das Template stehen - weil es ja Sache der IDE (VS) ist, welche Dateien es heranzieht und welche nicht.



  • Aber aus der Exe kannst du dir sowieso keine Funktionen rausgreifen - das ist ein fertiges Programm, das du ausführen und bei der Arbeit bewundern kannst. Um bestimmte Funktionen oder Klassen in deinen Programmen einsetzen zu können, benötigst du eine Lib.



  • Ich dachte das Template befände sich in einer Lib... Sorry.

    Die Templates werden vom Compiler aufgelöst und dem ist es ziemlich egal ob eine Exe oder eine Lib erzeugt wird.
    H-Files werden vor dem Übersetzen vom Precompiler in die Cpp-Dateien kopiert.
    Eine Template-Implementierung in einem Header wird somit auch in alle Cpp-Dateien vor dem Übersetzen hineinkopiert und ist dementsprechend auch zu jeder Zeit während des Übersetzens ausgeprägbar.
    Wenn die Implementierung des Templates in einer Cpp-Datei erfolgt, kann der Compiler das Template nur beim Übersetzen der Cpp-Datei ausprägen in der sich die Implementierung des Templates befindet. Da weiß der Compiler aber nicht so ohne weiteres welche Ausprägungen benötigt werden.
    Ich denke das macht es deutlich, dass es ein klein wenig komplexer ist die Templates aufzulösen wenn man es zuläßt die Deklaration eines Templates von seiner Implementierung auf Header- und Cpp-Datei zu verteilen...



  • CStoll schrieb:

    Aber aus der Exe kannst du dir sowieso keine Funktionen rausgreifen

    Ist mir natürlich klar, es ging aber darum:
    Wenn ich eine lib übersetze müssen die Definitionen und Deklarationen von Templates in die header Datei, was ja aus den ganzen Posts hervorgeht.
    Ich dachte jetzt, ich übersetz einfach mal eine .exe und schau ob es da ok ist, wenn die Deaklarationen in diesem Fall in der .cpp stehen - ist es nicht, was nach dem Post von Mathias auch einleuchtet.
    Was mich jetzt immer noch stört ist, dass der Funktionsassistent von VC das nicht gebacken bekommt und von vorne herein bei Templates alles in die Header-Datei schreibt - was aber nicht zu ändern ist.


Anmelden zum Antworten