undefined reference bei funktionstemplate in (nicht template) klasse



  • Hallo!

    Ich hab hier ein kleines Problemchen, und leider keine Ahnung worans liegt. Meiner meinung nach hab ich alles richtig deklariert.

    Also, ich hab ne Klasse, die keine Templateklasse ist. Diese hat eine Memberfunktion die ein Template ist.
    Diese Klasse ist in einer Datei, nennen wir sie foo.cpp und foo.h .
    Dann hab ich noch ne main.cpp, aus der das template aufgerufen wird.

    Wenn ich beide dateien kompiliere, gibts keine Fehler.
    Nur beim linken krieg ich nen fehler, dass das (jetzt spezialisierte) template nicht gefunden werden kann.

    Also hier sind die Dateien (möglichst aufs problem reduziert)

    foo.h:

    #ifndef FOO_H
    #define FOO_H
    
    class maxclass
    {
    
    public:
    
    	template<typename T>
    	T my_max(T a, T b);
    
    };
    
    #endif // FOO_H
    

    foo.cpp:

    #include "foo.h"
    
    template <typename T>	
    T maxclass::my_max(T a, T b)
    {
    
    	if (a > b)
    		return a;
    
    }
    

    main.cpp

    #include <iostream>
    
    #include "foo.h"
    
    int main()
    {
    	int a= 4, b= 2, c;
    
    	maxclass mc;
    
    	c = mc.my_max(a, b);
    
    	std::cout<<"c = "<<c<<'\n';
    
    	return 0;
    }
    

    Mein Compiler: gcc 4.1

    Das hier ist die linker fehlermeldung:
    (zuerst beide .cpp in .o kompiliert, fehlerfrei)

    g++ -o blub main.o foo.o schrieb:

    main.o: In function main': main.cpp:(.text+0xa6): undefined reference toint maxclass::my_max<int>(int, int)'
    collect2: ld returned 1 exit status



  • Bei Templates muss die Implementation in der Header erfolgen.

    #ifndef FOO_H
    #define FOO_H
    
    class maxclass
    {
    
    public:
    
        template <typename T>   
        T maxclass::my_max(T a, T b)
        {
            if (a > b)
                return a;
        }
    
    };
    
    #endif // FOO_H
    


  • Echt jetzt? Nur inline?

    Das ist aber blöd...

    Die richtige Template ist aber um einiges Länger und ich hätt das wirklich gern in der implementierungsdatei mit den anderen membern. Gibts da keinen weg drumherum?



  • Du kannst die Datei, in die du die implentierungen schreibst, einfach in die Header-Datei includen.



  • in die cpp geht nicht, weil die Templates zur Compilezeit bekannt sein müssen.
    Du kannst die Implementation der Template-Member in eine andere Datei auslagern, siehe hier


  • Mod

    DrPhil_Guth schrieb:

    Gibts da keinen weg drumherum?

    Wenn du weißt, welche Instanzen deines Templates du brauchst, kannst du diese per expliziter Instantiierung in foo.cpp erzeugen. Oder du nimmst einen Compiler, der export unterstützt.



  • camper schrieb:

    Wenn du weißt, welche Instanzen deines Templates du brauchst, kannst du diese per expliziter Instantiierung in foo.cpp erzeugen. Oder du nimmst einen Compiler, der export unterstützt.

    Das weiß ich leider nicht. Der Templateparameter wird nämlich an operator>> von stringstream weitergereicht, und ich will nichts einschränken, was den Benutzern meiner Klasse mit stringstreams so alles einfällt.

    Also werd ich wohl das ding mit der extradeitei nehmen müssen. Ist zwar auch nicht das wahre (es sollte eine kleine Klassenhirarchie zum Lesen von konfigurationsdateien werden, aber ich hab jetzt schon 2 * (.cpp + .h) 😞 ) aber wenn die anderen möglichkeiten alle so lau sind...



  • zum einen

    maxclass::
    

    gehört nicht in die Deklaration der maxclass-Klasse (der ICC wirft da brav warnigs)
    zum anderen kannst du die Funktion ausserhalb der Deklaration definieren:

    #ifndef FOO_H 
    #define FOO_H 
    
    class maxclass 
    { 
    public: 
       template <typename T>   
       T my_max(const T& a, const T& b); 
    }; 
    
    template <typename T>   
    T maxclass::my_max(const T& a, const T& b) 
    { 
       if (a > b) return a; 
       return b;
    } 
    #endif // FOO_H
    

    und bei Lust und Laune (z.B. aus Gründen der Übersichltichkeit) kannst du die Definitionen auf in eine .hpp, .impl Datei packen, die du dann dennoch nach der Deklaration im HEader einfügen musst. Ausser du hast einen Kompiler, der export untersützt, aber die Anzahl ist mehr als überschaubar.

    und was die lauen möglichkeiten anbelangt, so denk immer dran, was für eine schreibarbeit dir so ein template letztlich spart 😉 zudem verstehe ich nicht wieso die datei-zahl steigen sollte? wenn du alles im header hast, dann hast du sogar ne cpp, weniger. okay, die übersicht geht evtl irgendwann flöten und die compilierzeit steigt bei templates...


Anmelden zum Antworten