Pregunta

Tengo una clase, definida en una cabeza como:

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

En un archivo de aplicación, que tengo:

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

Lo que todo se ve bastante kosher. Sin embargo, cuando intento y el uso de este operador (es decir, std :: cout << MiClase ()), me sale el siguiente error de vinculador:

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

Me sorprende que el compilador no ha generado automagicially esto por mí ... Cualquier sugerencia en cuanto a lo que estoy haciendo mal?

¿Fue útil?

Solución

  

En un archivo de aplicación, que tengo:

Ese es el problema. No se puede dividir definiciones de plantilla entre los archivos de encabezado e implementación. Debido a la naturaleza de las plantillas, los compiladores de C ++ son meticulosos aquí. Definir todo el código en la cabecera para hacer que funcione.

De hecho, el problema aquí es que todas las definiciones de plantillas deben residir dentro de la misma unidad de compilación, porque el estándar de C ++ no define cómo la información de plantilla se comparte a través de diferentes unidades. Estas unidades se cosen por el enlazador, pero los genéricos se resuelven en tiempo de compilación (que es anterior), no en tiempo de enlace.

Teóricamente, el estándar de C ++ define una palabra clave, export, para manejar estos casos. En la práctica, no compilador implementa este (con una excepción?), Y no hay ninguna intención de cambiar esta situación porque el costo / utilidad disyuntiva no se considera lo suficientemente bueno.

Otros consejos

Muchas plantillas - esto funciona:

#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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top