Spezialisierte Template-Funktionen: in .h oder .cpp?



  • class Foo
    {
    public:
    
       template< typename T>
      void bar( T t);
    };
    
     template<>
    void Foo::bar<int>( int t)
    {
    }
    
     template<>
    void Foo::bar<const char*>(const char* txt)
    {
    }
    

    Gehören die beiden Spezialisierungen ins cpp-File oder in den Header???



  • dek. in .h + imp. in .cpp



  • Theoretisch: Egal. Da du diese Klasse / Template-Funktion aber wahrscheinlich in mehreren Source-Files benutzt würde ichs in eine Header-Datei schreiben und #includen.



  • Es muss natürlich in den Header. Wenn die Spezialisierung nicht im Header steht, weiß der Compiler beim nächsten Modul nicht, dass es sie gibt, und konkretisiert halt den Normalfall.



  • Header hab ich eigentlich auch gedacht.
    Mein VC++ 7.1 macht dann aber Linker-Fehler, dass das Symbol doppelt definiert ist. Leider kann ichs irgendwie net ganz nachvollziehen.
    Kennt jemand solche Probleme?



  • Tue die Spezialisierungen von der Methode in die cpp. Du hast ja diese schon explizit einen Typ zugewiesen (int + const char*) und das Template muss so nicht mehr erst gebaut werden zur Compile-Zeit.
    Das Symbol ist doppel definiert, weil 2 Übersetzungseinheiten (z.B. main.cpp und foo.cpp) beide die Spezialisierungen durch die foo.h definiert haben. So will das der Linker natürlich nicht und gibt dir die Fehlermeldung.
    Falls du eine allgemeine Version von Foo::bar() brauchst, kommt diese wieder in die Heider, da sie ja erst noch instanziiert werden muss. (Sonst hast du den alt bekannten Linker-Fehler, dass er z.B. Foo::bar<double>(..) nicht finden kann.)



  • kartoffelsack schrieb:

    Header hab ich eigentlich auch gedacht.
    Mein VC++ 7.1 macht dann aber Linker-Fehler, dass das Symbol doppelt definiert ist. Leider kann ichs irgendwie net ganz nachvollziehen.
    Kennt jemand solche Probleme?

    Ein klassisches Problem, das sich aber ganz einfach Lösen lässt. 😉 Also man sollte eine Header-Datei am besten in etwa so aufbaun:

    // Blablabla, kurze Beschreibung
    
    #ifndef _HEADER_
    #define _HEADER_ 
    
    // Alles andere bitte hier
    
    #endif
    

    Jetzt ist die Datei vor einer mehrfachen Übersetzung geschützt und kann beliebig oft included werden.



  • kartoffelsack schrieb:

    Header hab ich eigentlich auch gedacht.
    Mein VC++ 7.1 macht dann aber Linker-Fehler, dass das Symbol doppelt definiert ist. Leider kann ichs irgendwie net ganz nachvollziehen.
    Kennt jemand solche Probleme?

    mach mal die Methoden inline



  • Sorry Leute, versuche ein Projekt vom C++Builder auf VC++7.1 umzustellen und hab da so meine Probleme. Das komische ist, dass sich das Ding im 'echten' Code scheinbar völlig anders verhält als in einem kleinen Test-Projekt.
    Im C++Builder hatte ich die kompletten spezialisierungen in den Headern. Bei VC7.1 krieg ich nen Fehler wegen nicht-eindeutiger Symbole.

    @bloodlord
    so vermeidet man Compilerfehler. Nicht aber Linker-Fehler. Der Include-Wächter wirkt nur Modulweise (also pro cpp-File)

    Zum Problem:
    mE muss die spezialisierte Template-Funktion schon im Header zumindest bekanntgemacht werden, sonst weiß ja der Compiler net, dass es für einen Typ ne Spezialisierung gibt. Also hab ich mir gedacht, eigentlich wie bei normalen Funktionen: Prototyp in den Header, Implementierung ins cpp-File.

    Leider liefert folgender Code nen nen 'fatal error C1001: INTERNER COMPILERFEHLER'
    ---Header Foo.h---

    class Foo
    {
    public:
       template< typename T>
      T bar( int i);
    };
    
     template<>
    double Foo::bar<double>( int i);
    
     template<>
    int Foo::bar<int>( int i);
    

    --- main.cpp ---

    int main()
    {
      Foo foo;  
      double d( foo.bar<double>( 3));
    }
    

    In meinem richtigen Projekt funzt das aber anscheinend (nur da hab ich dann andere Probleme, die ich eigentlich im testprojekt nachvollziehen möchte).



  • kartoffelsack schrieb:

    mE muss die spezialisierte Template-Funktion schon im Header zumindest bekanntgemacht werden, sonst weiß ja der Compiler net, dass es für einen Typ ne Spezialisierung gibt. Also hab ich mir gedacht, eigentlich wie bei normalen Funktionen: Prototyp in den Header, Implementierung ins cpp-File

    Jo, klingt doch ganz logisch. Ist auch so, obwohl auch alles im Header sein kann. Aber irgendwie ist da was grottenfalsch. Das schluckt doch so kein Compiler, GCC und VC++ 8 jedenfalls nicht. Ich frage mich immernoch was du eigentlich willst?



  • Es kann eben nicht alles im Header sein.

    ssms Tipp mit dem inline hilft mir schonmal weiter. Jetzt hab ich nur noch an einer Stelle nen komischen Fehler ...



  • kartoffelsack schrieb:

    Jetzt hab ich nur noch an einer Stelle nen komischen Fehler ...

    was für einen?



  • ok, das inline wars.

    Ist eigentlich logisch, die definition darf nicht mehrmals vorkommen, außer es sind inline-Funktionen. Das mit den Prototypen überfordert den VC7.1 allerdings anscheinend.

    @all: DANKE 🙂

    Jetzt kann ich mich endlich wieder meinen eigentlichen Programmierproblemen zuwenden (hoffentlich)



  • Versuche es mal so:

    Foo.h:
    dort wird alles definiert
    z.B int foo(std::string);

    Foo.cpp:
    #include "Foo.h";
    dort wird es jetzt ernst 😉
    z.b int foo(std::string &a){ std::cout<<a; return 1; }

    main.cpp:
    #include "Foo.h";
    ....

    g++ -c Foo.cpp -o Foo.o
    g++ main.cpp Foo.o -o Prog

    MFG Ghost



  • Green_Ghost schrieb:

    Foo.h:
    dort wird alles definiert
    z.B int foo(std::string);

    Hier wird aber nichts definiert!

    Zudem haben deine Deklaration und Definition unterschiedliche Signaturen. Das gibt mit Sicherheit Linkerfehler.

    Ansonsten ist dein Beitrag vollkommen OT. Templates haben nunmal ihre Eigenheiten.



  • ich häng mich hier mal mit rein mit einem ähnlichen problem...

    was ist, wenn ich das template habe:

    template <class T> ausgabe(T inhalt);
    

    und es wie folgt spezialisieren möchte:

    template <> ausgabe<teststruct>(teststruct inhalt);
    

    wobei teststruct ein struct in einer anderen header ist (das prog besteht aus mehreren quelltextdateien).

    wo muss ich das dann hinschreiben 😕


Anmelden zum Antworten