Domanda

Ho una classe, definita in un testa come:

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

In un file di implementazione, ho:

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

Il che tutto sembra abbastanza kosher. Tuttavia, quando cerco di utilizzare questo operatore (vale a dire std :: cout << MyClass ()), ottengo il seguente errore di linker:

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

Sono sorpreso il compilatore non ha automagicially generato questo per me ... Dei suggerimenti quanto a quello che sto facendo male?

È stato utile?

Soluzione

  

In un file di implementazione, ho:

Questo è il problema. Non è possibile dividere le definizioni di modello tra i file di intestazione e di implementazione. A causa della natura dei modelli, i compilatori C ++ sono meticolosi qui. Definire tutto il codice nell'intestazione per farlo funzionare.

In realtà, il problema qui è che tutte le definizioni di template devono risiedere all'interno della stessa unità di compilazione in quanto lo standard C ++ non definisce come le informazioni del modello sono condivise tra diverse unità. Queste unità sono cuciti insieme dal linker, ma generici vengono risolte al momento della compilazione (sia anteriore), non in fase di collegamento.

In teoria, lo standard C ++ definisce una parola chiave, export, per gestire questi casi. In pratica, non compilatore implementa questa (con una sola eccezione?), E non v'è alcuna intenzione di cambiare questo perché il costo / utilità trade-off non è considerato sufficiente.

Altri suggerimenti

Troppi modelli - questo funziona:

#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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top