template nur in header?



  • Hallo,
    Ich wollte einmal etwas mit Templates probieren, so dass meine Klasse bzw. Funktion allgemeiner ist und somit wieder verwendet werden kann.

    z.B.:
    header datei:

    //autohaus.h
    #ifndef AUTOHAUS_H
    #define AUTOHAUS_H
    
    template<typename T>
    class Autohaus{
        public:
           Autohaus(T t);
    };
    
    template <typename T>
    void autofun(T t);
    
    #endif
    

    Implementierung

    //autohaus.cpp
    #include "autohaus.h"
    #include <iostream>
    
    template<typename T>
    Autohaus<T>::Autohaus(T t){
    	std::cout << "auto Konstrukor" << std::endl;
    
    }
    
    template<typename T>
    void autofun(T t){
    	std::cout << "auto fun" << std::endl;
    }
    

    main datei:

    //main.cpp
    #include "autohaus.h"
    
    int main(){
    	Autohaus<int> ah(42);
    
    	autofun(ah);
    }
    

    Wenn ich es nun kompiliere mit:

    g++ main.cpp autohaus.cpp
    

    kommt:

    main.cpp:(.text+0x25): undefined reference to `Autohaus<int>::Autohaus(int)'
    main.cpp:(.text+0x2f): undefined reference to `void autofun<Autohaus<int> >(Autohaus<int>)'
    

    wenn ich in die cpp:

    void test(){
    	Autohaus<int> ahi(42);
    	autofun(ahi);
    }
    

    einfüge geht es, da er für "int" den Code generiert hat.

    Gibt es da eine schönere Lösung für?

    Ich habe schon im Internet nach einen Lösung gesucht aber bisher nicht zufriedenstellend. Eine Möglichkeit wäre alle Templates in den header zu machen.
    Die andere in ein einer ".tpp"-Datei, die wiederum im header am Ende included wird.
    Ich würde die Definitionen der Funktionen gerne in der cpp Datei machen (oder sollte ich das lieber sein lassen?).
    Gibt es auch eine Möglichkeit in der main.cpp etwas hinzuschreiben, dass er Code für "Autohaus<int>" generieren soll (die autohaus.cpp müsste dann immer mit der main.cpp zusammen kompiliert werden, oder?)?



  • An der Uni haben wir gezeigt bekommen, dass man in einer .cpp Datei alles definiert und dann sowohl den Header, als auch die Source Datei inkludiert. In Deinem Fall:

    //main.cpp
    #include "autohaus.h"
    #include "autohaus.cpp"
    
    int main(){
        Autohaus<int> ah(42);
    
        autofun(ah);
    }
    

    So würde ich das nicht machen!

    Ich kenne den Aufbau so:

    // header file.hpp
    
    // ...
    
    #include "file.inl"
    
    // file.inl
    // Definition
    
    #include "file.hpp"
    
    int main()
    {
    }
    


  • Hallo Bernd77

    Bernd77 schrieb:

    Ich habe schon im Internet nach einen Lösung gesucht aber bisher nicht zufriedenstellend. Eine Möglichkeit wäre alle Templates in den header zu machen.
    Die andere in ein einer ".tpp"-Datei, die wiederum im header am Ende included wird.

    Das sind die einzigen zwei Optionen. Die Datei, die man am Ende des Headers inkludiert, lässt man jedoch üblicherweise auf .inl enden, .tpp ist mir pers. neu.

    Bernd77 schrieb:

    Ich würde die Definitionen der Funktionen gerne in der cpp Datei machen (oder sollte ich das lieber sein lassen?).

    Beides hat Vor- und Nachteile. Die Header-only-Herangehensweise hat den Vorteil, dass die Integration in ein bestehendes Projekt einfacher ist (lediglich Include-Paths, keine Linkage...) und erlaubt i.d.R. aggressivere Optimierungen. Zu den Nachteilen zählen höhere Compile-Zeiten und größere Binaries.
    Unter dem Strich ist festzuhalten: Es gibt Wege, wie du die Definitionen von Templates in eine eigene TU auslagern oder es zumindest emulieren kannst (Explizite Instanziierung, Type Erasure, ...). Üblich ist das jedoch nicht. Normalerweise definiert man entweder alles im Header oder getrennt in hpp/inl-Dateien (siehe Boost / Eigen).

    Bernd77 schrieb:

    Gibt es auch eine Möglichkeit in der main.cpp etwas hinzuschreiben, dass er Code für "Autohaus<int>" generieren soll (die autohaus.cpp müsste dann immer mit der main.cpp zusammen kompiliert werden, oder?)?

    Ja, diese Möglichkeit gibt es, nennt sich explizite Instanziierung. Diese müsstest du aber in die autohaus.cpp packen und für jede neue Template-Parameter-Kombination, die du irgendwo im Projekt benutzt, musst du manuell eine Zeile in autohaus.cpp ergänzen: extrem unpraktisch!

    LG



  • Hallo HarteWare

    HarteWare schrieb:

    An der Uni haben wir gezeigt bekommen, dass man in einer .cpp Datei alles definiert und dann sowohl den Header, als auch die Source Datei inkludiert.

    Anti-Pattern des Jahres. 🙂

    LG


Log in to reply