2009-06-18 17 views
0

In der Regel für meine Template-Klassen, schließe ich Deklarationen in eine .hpp Datei und Vorlage Implementierungscode in eine .t.hpp Datei. Ich instanziiert explizit die Klasse in einer .cpp Datei:Vorlagenoperator << explizite Instanziierung und Header

template class MyClass<AnotherClass>; 

dessen Objektcode wird in einer Bibliothek setzen.

Das Problem ist, dass, wenn ich versuche, das Objekt mit operator<<, zu drucken, die in der .hpp Datei deklarierte und in der .t.hpp Datei wie folgt definiert:

template<class T> 
std::ostream& operator<<(std::ostream& os, const MyClass<T>& c) 
{ 
    os << "Hello, I am being output."; 
    return os; 
} 

ich eine Linker Fehlermeldung, dass das richtige Symbol ist nicht definiert.

Ich verstehe, dass dies liegt daran, dass diese Template-Funktion nicht explizit instanziiert wird, wenn die Klasse ist. Gibt es eine Möglichkeit, um diese andere zu umgehen als die .t.hpp Datei zu jeder Zeit, die ich operator<< auf der Klasse verwenden möchten, oder den Vorlagencode in die .hpp Datei zu verschieben? Kann ich den Funktionscode explizit instanziieren?

Antwort

2

Sie können explizit Funktionsschablonen instanziiert

template std::ostream& operator<<(std::ostream&, const MyClass<int>&); 

Um eine Spezialisierung mit T = int instanziiert. Die Schablonenargumentklammern können weggelassen werden, wenn alle Schablonenargumente abgeleitet werden können (wie in diesem Fall vom Typ MyClass<int>). Wenn dies nicht möglich ist, zB weil die Schablonenparameter nicht in einem Funktionsparametertyp vorkommen, müssen Sie explizit geben Sie es

template<typename T> void f() { } 
template void f<int>(); 
+0

+1. Ich habe gerade den nicht-abgeleiteten Fall hinzugefügt und sehe dich bereits aktualisiert, um das aufzunehmen ... Grr! :) –

+0

Danke! Genau das habe ich gebraucht. Ich wusste nicht, dass Vorlagenfunktionen explizit instanziiert werden könnten. –

2

litb's solution Siehe

Für Ihren speziellen Fall der Compiler alle Template-Argumente aus dem Parameter ableiten kann und Typen zurück, aber wenn es nicht könnte man sie explizit geben könnte.

template std::ostream& operator<< <T>(std::ostream&, const MyClass<T>&); 

Dies ist immer noch erlaubt, wenn die Template-Argumente abgeleitet werden können.

Darf ich fragen: Gibt es einen Grund, warum Sie es vorziehen, alles explizit zu instanziieren? Sie machen ziemlich viel Arbeit für sich. Sie werden sicherlich die Zeit für die Kompilierung sparen, indem Sie den Quellcode der Vorlage nicht überall mit einbeziehen, aber lohnt es sich in der Entwicklerzeit?

+0

Ich habe genau die gleiche Frage. IMHO in den meisten Fällen Entwicklerzeit> Ausführungszeit> Kompilierungszeit. –

+0

Dies ist für einen wissenschaftlichen Rechencode. Eine Menge meines Codes ist in der Dimension templatiert: d. H. Der Template-Parameter ist ein vorzeichenloser Int, der 1, 2 oder 3 sein kann, abhängig davon, ob ich ein 1-D-Problem oder was auch immer habe. Die Ausführungszeit ist von größter Wichtigkeit, und das bisschen zusätzliche Entwicklerzeit (da ich den Vorlagenparameter praktisch nie ändern oder weitere Klassen hinzufügen muss) ist die zusätzliche Kompilierungszeit wert: Ich archiviere den endgültigen Vorlagencode in einer statischen Bibliothek, die mit den verschiedenen Frontends, Komponententests usw. verbunden ist –

+0

@Seth: Ausführungszeit für explizit instanziierten Code wird niemals besser sein als implizit instanziierter Code und oft schlechter, weil der Compiler das Inlining nicht ausführen kann - dafür muss der Quellcode der Vorlage angezeigt werden. Dies kann bei engen Schleifen einen großen Unterschied machen. (Sie sollten jedoch eine vorhandene CPU-abgestimmte Bibliothek für numerische Primitive wie Matrixmultiplikation verwenden, da sie normalerweise noch viel schneller sind.) –