Template, Veraerbung



  • Code-Hacker schrieb:

    Das liegt nicht am Builder, das ist bei MSVS genau so. Du musst wenn du die Unterteilung in .h und .cpp haben willst in der Header bei der Klassendeklaration "export" davor schreiben:

    export template <class f>
    class X
    {...}
    

    Der MSVS unterstützt "export" nicht. Beim Builder weiß ich es nicht, das musst du in der Referenz nachsehen. Ansonsten bei templates alles in die Headerdatei, so wird es von allen Compilern angenommen.

    Code-Hacker

    erzähl bitte keinen Unsinn. Das export Schlüsselwort ist für Funktion-Templates und non-inline Elementfunktion-Templates gedacht. Außerdem läßt sich mit VC7.1 folgendes problemlos kompilieren

    //h
    template<class T>
    class B
    {
    public:
    	void foo();
    };
    
    //cpp
    template<class T>
    void B<T>::foo()
    {
    }
    
    //...
    
    B<int> b;
    n.foo();
    


  • Genau sowas lies sich bei mir mit dem VC7.1 nicht kompilieren. Da kam der selbe Fehler wie im Builder.
    In einem Buch habe ich gelesen das die Aufteilung nicht in der ursprünglichen Natur läge musste dieses Schlüsselwort eingeführt werden um dem Compiler mitzuteilen das sich Template-Definition und Template-Methoden-Definitionen in unterschiedlichen Dateien befinden, dazu ein Beispiel:

    export template<class Typ, int S>
    class Feld
    {
      blalbla...
    };
    

    Habe eben aber nochmal in "Die C++-Programmiersprache" geguckt und mich eines besseren belehren lassen. Muss ich nochmal gucken ob ich da falsch gemacht habe bei meinem Template. Mich wundert nämlich das es, wenn ich es nur in der .h habe, funktioniert und getrennt nicht übersetzt wird.

    Code-Hacker



  • Code-Hacker schrieb:

    Genau sowas lies sich bei mir mit dem VC7.1 nicht kompilieren. Da kam der selbe Fehler wie im Builder.
    In einem Buch habe ich gelesen das die Aufteilung nicht in der ursprünglichen Natur läge musste dieses Schlüsselwort eingeführt werden um dem Compiler mitzuteilen das sich Template-Definition und Template-Methoden-Definitionen in unterschiedlichen Dateien befinden, dazu ein Beispiel:

    export template<class Typ, int S>
    class Feld
    {
      blalbla...
    };
    

    Habe eben aber nochmal in "Die C++-Programmiersprache" geguckt und mich eines besseren belehren lassen. Muss ich nochmal gucken ob ich da falsch gemacht habe bei meinem Template. Mich wundert nämlich das es, wenn ich es nur in der .h habe, funktioniert und getrennt nicht übersetzt wird.

    Code-Hacker

    Du hast schon recht mit dem Schluesselwort export.

    Andernfalls, muss eine template-Funktion in jeder Implementationsdatei
    definiert werden, oder es kann sein, dass der Compiler die Definition einer
    solchen Funktion nicht findet und dann meldet sich der Linker.

    mfg
    v R



  • Stimmt. Kompilieren geht, Linken geht nicht.

    Code-Hacker



  • falls du das kleine Beispiel aus meinem vorherigen Posting meinst, dann geht beides sonst hätte ich es erwähnt.



  • Also ich habe eben mit VS7.1 dein Template benutzt und das versucht. Funktionierte nicht. Es kam folgender Fehler:

    CPPTests error LNK2019: Nicht aufgelöstes externes Symbol '"public: void __thiscall B<int>::foo(void)" (?foo@?$B@H@@QAEXXZ)', verwiesen in Funktion '_main'

    So sehen die Dateien aus:
    test.cpp:

    #include "test.h"
    
    template<class T>
    void B<T>::foo()
    {
    }
    

    test.h:

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

    main.cpp

    #include <iostream>
    #include "test.h"
    
    int main()
    {
      B<int> n;
      n.foo();
      std::cin.get();
    }
    

    Mache ich irgendwas falsch???

    EDIT:
    Wenn ich test.h wie folgt ändere funktioniert es:

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

    Code-Hacker



  • füge in die main.cpp folgendes ein

    #include "test.cpp"
    


  • Das ist aber übler Stil und hat nichts mit export zu tun. cpps gehören nicht inkludiert.



  • operator void schrieb:

    Das ist aber übler Stil und hat nichts mit export zu tun. cpps gehören nicht inkludiert.

    Die Endung .cpp ist schlecht gewählt, aber so ein #include ist gängige Praxis.



  • Ich würde als Endung *.inl vorschlagen.



  • Shlo schrieb:

    füge in die main.cpp folgendes ein

    #include "test.cpp"
    

    Das ist exakt _das_ was CodeHacker und ich sagten und _kein_ Unsinn gewesen!

    Wenn du kein export hast, benoetigst du die Implementation der templates in
    jeder Implementationsdatei, in welcher du die Templates einsetzt, nicht mehr
    und nicht weniger hab ich gesagt.

    mfg
    v R



  • Es gibt noch eine Möglichkeit, die explizite Instantiierung heisst.

    //die Zeile gehoert zu der Cpp-Datei
    template class B<int>;
    


  • desert pinguin schrieb:

    Es gibt noch eine Möglichkeit, die explizite Instantiierung heisst.

    //die Zeile gehoert zu der Cpp-Datei
    template class B<int>;
    

    😮 😕

    Schon. Und so kann ich eine Funktion schreiben, die 42 zurückgibt:

    int zweiundvierzig ()
    {
       return 42;
    }
    

    😕



  • Ach ja, eigentlich schreibt man in solchen Fällen ja einfach ein 99 Bottles of Bear programm als Antwort:

    module Main where
    
    newtype Bottle = Bot Int
    
    instance Show Bottle where
      show (Bot 0) = "No more bottles"
      show (Bot 1) = "1 bottle"
      show (Bot n) = show n ++ " bottles"
    
    data Line = Simple String | Complex Bottle String
    
    instance Show Line where
      show (Simple s)    = s
      show (Complex b s) = show b ++ s
    
    verse n = [Complex (Bot n) " of beer on the wall,",
    	   Complex (Bot n) " of beer.",
    	   Simple "Take one down pass it around",
    	   Complex (Bot $ n-1) " of beer on the wall.\n"]
    
    main = do mapM print $ concatMap verse [99, 98 .. 1]
    


  • Helium schrieb:

    desert pinguin schrieb:

    Es gibt noch eine Möglichkeit, die explizite Instantiierung heisst.

    //die Zeile gehoert zu der Cpp-Datei
    template class B<int>;
    

    😮 😕

    Schon. Und so kann ich eine Funktion schreiben, die 42 zurückgibt:

    int zweiundvierzig ()
    {
       return 42;
    }
    

    😕

    Ich wollte nur sagen, dass in diesem Fall keine cpp-Datei beinhalten werden muss. Nur die header-datei.



  • Shade Of Mine schrieb:

    Die Endung .cpp ist schlecht gewählt, aber so ein #include ist gängige Praxis.

    Wenn jemand die Elementfunktionen in eine separate Datei steckt, soll er das von mir aus tun (auch wenn ich keinen Vorteil darin sehe?), aber .cpp und MSVC klingt schon warnenswert. Vor allem, weil es anfangs problemlos funktioniert und erst später zu Fehlern führt, wenn man z.B. eine nicht-template-Hilfsfunktion definiert. (Klar kann man die Kompilierung für einzelne Dateien abschalten, aber das ist auch nicht Sinn der Sache...)


Anmelden zum Antworten