undefined reference bei templates



  • Hey,

    ich bin mir nicht sicher ob es mein Fehler ist oder der meines Compilers (g++ 4.2.1). Ich habe folgende Header-Datei (Ausschnitt):

    template<typename id_type, int ID_LEN, int STR_MAX, int SHIFT_SIZE>
    unsigned int get_db_id(const char* search_name, const char* db_file);
    
    inline unsigned int get_pilot_id(const char* search_name) {
    	return get_db_id<unsigned int, 4, 28, 5>(search_name, "pilots.dat"); // l. 30
    }
    
    inline unsigned int get_mod_id(const char* search_name) {
    	return get_db_id<unsigned short, 2, 30, 5>(search_name, "mods.dat"); // l. 34
    }
    
    inline unsigned int get_mission_id(const char* search_name) {
    	return get_db_id<unsigned int, 4, 60, 5>(search_name, "missions.dat");
    }
    
    inline unsigned int get_server_id(const char* search_name) {
    	return get_db_id<unsigned short, 2, 30, 5>(search_name, "servers.dat");
    }
    

    Dabei ist die obere Funktion in einer CPP-Datei, die diese Datei includet, implementiert. Der Compiler compiliert zunächst, spuckt aber beim Linken dann Errors aus:

    ./main.o: In function `get_mod_id':
    /home/johannes/cprogs/stats_project/stats_reader/./db.h:34: undefined reference to `unsigned int get_db_id<unsigned short, 2, 30, 5>(char const*, char const*)'
    ./main.o: In function `get_pilot_id':
    /home/johannes/cprogs/stats_project/stats_reader/./db.h:30: undefined reference to `unsigned int get_db_id<unsigned int, 4, 28, 5>(char const*, char const*)'
    /home/johannes/cprogs/stats_project/stats_reader/./db.h:30: undefined reference to `unsigned int get_db_id<unsigned int, 4, 28, 5>(char const*, char const*)'
    collect2: ld returned 1 exit status
    

    Ich verstehe nicht
    - wo mein Fehler ist
    - warum er es nur bei den OBERSTEN ZWEI template-funktion-aufrufen meckert, bei den unteren zwei dagegen nicht. Wenn ich Zeile 30 und 34 auskommentiere, übersetzt er die Datei obskurer Weise 😮
    - warum er den Fehler in Zeile 30 gleich ZWEI mal vermerkt, den aus 34 nur einmal

    Auf Support freut sich
    voidpointer 😉

    PS.: Bin nun einen Schritt weiter! Der zweite Punkt könnte daher kommen, dass die Funktionen in Zeile 30 und 34 tatsächlich von der main.cpp aufgerufen werden, die anderen eiden sind noch unbenutzt



  • Wo ist den die Implementierung von dem?

    template<typename id_type, int ID_LEN, int STR_MAX, int SHIFT_SIZE>
    unsigned int get_db_id(const char* search_name, const char* db_file);
    


  • "Dabei ist die obere Funktion in einer CPP-Datei, die diese Datei includet, implementiert. " -> Damit meinte ich diese Funktion



  • voidpointer schrieb:

    "Dabei ist die obere Funktion in einer CPP-Datei, die diese Datei includet, implementiert. " -> Damit meinte ich diese Funktion

    Templates müssen immer vollständig definiert sein (Sprich: Definition bei Templates bitte in den Header packen).

    cu André



  • was fehlt denn an meiner definition im header noch?



  • Die definition der template-Funktion fehlt im Header noch. Da steht nur eine Deklaration.



  • Grundsätzlich ist es üblich Templates komplett im Header zu halten (und keine .cpp) anzulegen.

    Ich nenne mal die mir bekannten zwei Alternativen:
    a) Man schreibt die Definition in eine eigene Datei (nennt sie dann aber möglichst nicht .cpp sondern z.B. .tmpl) und includiert diese am Ende des Headers. Dabei ist aber zu Beachten das alles was für Header gilt, auch für diese Datei gilt (z.B. sollte man dort kein using namespace verwenden).

    b) Das Schlüsselwort export im Zusammenhang mit Templates. Da es bisher aber nur von einem oder zwei Compilern (mir ist jetzt nur der Comeau bekannt) unterstützt wird, ist diese Lösung eher nicht sinnvoll.

    cu André



  • Ah ok die Definition könnte ich schon in die header-datei tun. aber das soll man doch eigentlich nicht machen, oder? Hatte mal einen älteren g++ (3.0 oder so), der Header-Dateien mit Definitionen nicht kompilieren wollte (wegen multiple declaration oder so).



  • voidpointer schrieb:

    Ah ok die Definition könnte ich schon in die header-datei tun. aber das soll man doch eigentlich nicht machen, oder? Hatte mal einen älteren g++ (3.0 oder so), der Header-Dateien mit Definitionen nicht kompilieren wollte (wegen multiple declaration oder so).

    Doch. Das ist eigentlich üblich die im Header zu schreiben. Ältere Compiler hatten mit Templates Probleme. Das haben sie Heute eigl. nicht mehr.



  • voidpointer schrieb:

    Ah ok die Definition könnte ich schon in die header-datei tun. aber das soll man doch eigentlich nicht machen, oder? Hatte mal einen älteren g++ (3.0 oder so), der Header-Dateien mit Definitionen nicht kompilieren wollte (wegen multiple declaration oder so).

    Das stimmt zwar einerseits und andererseits auch nicht.
    - Für "normale Funktionen" stimmt das (=> Implementation auslagern)
    - Für templates ist es genau anders herum (=> Implementation mit in den Header)

    Das liegt an den speziellen Eigenschaften der templates (es sind eben keine Funktionen, sondern die Funktionen werden erst vom Compiler erzeugt).

    Gruß,

    Simon2.



  • ah ok danke!


Anmelden zum Antworten