2009-03-16 13 views
28

Ich habe eine Funktion wie so erklärt:C++ Vorlagen, undefined reference

template <typename T> 
T read(); 

und definiert wie folgt:

template <typename T> 
T packetreader::read() { 
    offset += sizeof(T); 
    return *(T*)(buf+offset-sizeof(T)); 
} 

Allerdings, wenn ich versuche, es zu verwenden, in meiner Funktion main():

packetreader reader; 
reader.read<int>(); 

bekomme ich folgende Fehler von g ++:

g++ -o main main.o packet.o 
main.o: In function `main': 
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()' 
collect2: ld returned 1 exit status 
make: *** [main] Error 1 

Kann jemand mich in die richtige Richtung?

+0

möglich Duplikat implementieren [undefiniert Referenzvorlage funktionieren, wenn sie mit string (GCC) verwendet] (http: // Stackoverflow.com/questions/614233/undefined-Referenz-zu-Funktion-Vorlage-wenn-verwendet-mit-String-gcc) – outis

Antwort

24

Sie müssen die export Schlüsselwort verwenden. Ich glaube jedoch nicht, dass G ++ die richtige Unterstützung bietet. Daher müssen Sie die Definition der Vorlagenfunktion in die Kopfzeile aufnehmen, damit die Übersetzungseinheit sie verwenden kann. Dies liegt daran, dass die '<int>' Version 'der Vorlage nicht erstellt wurde, nur die <typename T>' Version. '

Eine einfache Möglichkeit ist #include die CPP-Datei. Dies kann jedoch Probleme verursachen, z. wenn sich andere Funktionen in der CPP-Datei befinden. Es wird auch wahrscheinlich die Kompilierzeit erhöhen.

Eine saubere Art und Weise ist Ihre Template-Funktionen in seine eigenen CPP-Datei zu bewegen, und beinhaltet, dass im Header oder das export Schlüsselwort verwenden und separat kompiliert.

More information on why you should try and put template function definitions in its header file (and ignore export altogether).

+0

Wäre es eine gute Idee für mich, meine packet.cpp-Code in packet.h zu verschieben und umzubenennen etwas wie "packet.hpp", wie ich es oft im Boost gesehen habe? –

+1

@Daniel, Nur wenn alle Ihre Funktionen Vorlagenfunktionen sind. Andernfalls können Sie einige Ihrer Funktionen verschieben und die CPP-Datei beibehalten. – strager

4

Die beste Praxis mit Template-Funktionen ist es, sie in der Header-Dateien zu definieren. Sie werden zur Kompilierzeit erstellt, daher muss der Compiler eine Definition dafür haben.

Wenn export für Vorlagen mehr dies nicht der Fall, obwohl es kaum verwendet werden kann, nach wie vor aber jetzt würde unterstützt werden würde.

+0

Ich empfehle nicht, 'export' zu verwenden. Laut http://www.parashift.com/c++faq-lite/templates.html#faq-35.14 wurde es aus dem C++ 0x-Standard gestrichen. – uckelman

12

Das Problem ist, dass eine Funktionsvorlage keine Funktion ist. Es ist eine Vorlage zum Erstellen von Funktionen nach Bedarf. So

für eine Vorlage arbeiten, der Compiler muss intuitiv zwei Informationen: Die Vorlage selbst, und die Art, die in sie ersetzt werden soll. Dies ist anders als ein Funktionsaufruf, den der Compiler generieren kann, sobald er weiß, dass die Funktion existiert. Es muss nicht wissen, was die Funktion macht, nur dass es aussieht wie void Frobnicate(int, float) oder was auch immer seine Signatur ist.

Wenn Sie die Funktion Vorlage deklarieren, ohne ihn zu definieren, sind Sie nur sagen dem Compiler, dass eine solche Vorlage existiert, aber nicht, wie es aussieht. Das ist nicht genug für den Compiler, um es instanziieren zu können, es muss in der Lage sein, die vollständige Definition zu sehen. Die übliche Lösung besteht darin, die gesamte Vorlage in eine Kopfzeile einzufügen, die bei Bedarf eingefügt werden kann.

0

Ist ihre Compiler-Support-Vorlage separate Kompilierung?

Wie ich weiß, die gängige Praxis ist, zu erklären und Template-Funktionen in der Header-Datei

+0

Comeau glaube ich. Und eine moderne Version von MSVC * könnte * aber ich habe das selbst nicht überprüft. – vava

+0

Der neueste VS2008 unterstützt das Exportschlüsselwort noch nicht. Es scheint, dass MS-Leute dieses Schlüsselwort für zukünftige Unterstützung reserviert haben: warning C4237: Das Schlüsselwort 'export' wird noch nicht unterstützt, ist aber für die zukünftige Verwendung reserviert –

Verwandte Themen