Frage

Ich habe eine Klasse, in einem Kopf wie folgt definiert:

template <typename T> class MyClass
{
   template <typename U> friend std::ostream& operator<<(std::ostream& output, const MyClass<U>& p);
   public:
      ...
}

In einer Implementierungsdatei, die ich habe:

template <typename U> std::ostream& operator<<(std::ostream& output, const MyClass<U>& m)
{
   output << "Some stuff";
   return output;
}

, die alle ziemlich koscher aussieht. Allerdings, wenn ich versuche, und verwenden Sie diesen Operator (das heißt std :: cout << MyClass ()), erhalte ich die folgenden Linkerfehler:

Undefined symbols: std::basic_ostream<char, std::char_traits<char> >& operator<< <InnerType>(std::basic_ostream<char, std::char_traits<char> >&, MyClass<InnerType> const&)

Ich bin überrascht, hat der Compiler nicht automagicially dies erzeugt für mich ... Irgendwelche Vorschläge, was ich falsch mache?

War es hilfreich?

Lösung

  

In einer Implementierungsdatei, die ich habe:

Das ist das Problem. Sie können keine Template-Definitionen zwischen Kopf- und Implementierungsdateien aufgeteilt. Aufgrund der Art der Vorlagen, C ++ Compiler sind hier pingelig. Definieren Sie den gesamten Code in der Kopfzeile, damit es funktioniert.

In der Tat ist das Problem hier, dass alle Template-Definitionen innerhalb derselben Übersetzungseinheit befinden muss, weil die C ++ Standard definiert nicht, wie Template-Informationen werden über verschiedene Einheiten geteilt. Diese Einheiten werden zusammengenäht durch den Linker, aber Generika sind bei der Kompilierung aufgelöst (die früher ist), nicht zur Verknüpfungszeit.

Theoretisch der C ++ Standard definiert ein Schlüsselwort, export, diese Fälle zu behandeln. In der Praxis nicht Compiler implementiert diese (mit einer Ausnahme?), Und es ist nicht beabsichtigt, dies zu ändern, weil die Kosten / Nutzen Kompromiss nicht gut genug betrachtet wird.

Andere Tipps

Zu viele Vorlagen - das funktioniert:

#include <iostream>
using namespace std;
template <typename T> struct MyClass {

    friend ostream & operator << ( ostream & os, MyClass<T> & c ) {
        os << "MyClass\n";
        return os;
    }
};

int main() {
    MyClass <int> c;
    cout << c;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top