[gelöst] Linkerfehler bei template member-Funktion, obwohl explizit instantiiert



  • Hallo,

    ich habe eine Klasse mit einer Template-Memberfunktion. Alle instantiierungen sind vorher schon bekannt. Ich möchte die Funktion ungern im .h-File inlinen, sondern im .cpp file stehen lassen.

    Damit das gut geht, muss ich den Compiler ja zwingen, sie einmal explizit zu instantiieren, für alle Paramter die auftreten werden.

    Trotzdem erhalte ich beim linken der Applikation einen Linkerfehler.

    Die .h-Datei:

    class Foo {
    public:
        template <typename T>
        void bar (T* t);
    };
    
    template void Foo::bar<int>(int* t);
    template void Foo::bar<float>(float* t);
    

    die .cpp-Datei:

    template <typename T>
    void Foo::bar(T* t)
    {
        frobnicate(t);
    }
    

    Beim Linken erhalte ich dann den Fehler "undefined reference to 'Foo::bar(float*)'".
    Wenn ich die implementierung in die .h-Datei schreibe geht's natürlich.

    Ich dachte, sobald man den Compiler zum expliziten instantiieren zwingt (was ich m.Mn. in den letzten zwei Zeilen von .h tue), würde das nicht auftreten.

    Philipp


  • Mod

    template void Foo::bar<int>(int* t);
    template void Foo::bar<float>(float* t);
    

    Das muss in die cpp-Datei.



  • SeppJ schrieb:

    template void Foo::bar<int>(int* t);
    template void Foo::bar<float>(float* t);
    

    Das muss in die cpp-Datei.

    Gleiches Ergebnis. Linker mault trotzdem.

    Kompiler ist übrigens gcc 4.5.


  • Mod

    PhilippM schrieb:

    Gleiches Ergebnis. Linker mault trotzdem.

    Kompiler ist übrigens gcc 4.5.

    Das sollte nicht so sein. Was tust du denn genau? Hier Schritt für Schritt Anleitung (getestet mit gcc 4.4):

    foo.h:

    class Foo {
    public:
        template <typename T>
        void bar (T* t);
    };
    

    foo.cc:

    #include"foo.h"
    
    template <typename T>
    void Foo::bar(T* t)
    {
      // Dein Code
    } 
    
    template void Foo::bar<int>(int* t);
    template void Foo::bar<float>(float* t);
    

    main.cc:

    #include "foo.h"
    
    int main()
    {
      Foo foo;
      int *a;
      foo.bar<int>(a);
    }
    

    Compilierbar auf alle gängigen Arten und Weisen.



  • Disregard all after good morning.

    Klarer Fall von Facepalm: ich habe nicht das Projekt rekompiliert, das ich dachte das ich rekompiliert habe.
    Es geht natürlich so.

    Vielen Dank für die Hilfe, Thread kann geschlossen werden.


Anmelden zum Antworten