2012-07-30 18 views
5

¿Cuál es la forma correcta de declarar una función amiga de una clase de plantilla (para el std :: ostream & operador < <) en un archivo .cpp?C++: Función amigo en una clase de plantilla para el operador <<

Mi implementación actual no funciona:

// MyTest.h 
template<class T, unsigned int TSIZE> class MyTest 
{ 
    inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs); 
}; 

// MyTest.cpp 
template<class T, unsigned int TSIZE> inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs) 
{ 
    // IMPLEMENTATION 
} 

Muchas gracias!

+0

¿Qué quiere decir exactamente con "does not work" ... errores del compilador? ¿Qué errores? Primero adivine ... "amigo" no pertenece a la versión .cpp. –

Respuesta

7

Para hacer referencia al operator<< <T, TSIZE> como usted lo hace, que es una especialización de plantilla, una declaración de la plantilla primaria debe estar visible. A su vez, operator<< necesita una declaración de MyTest porque aparece como un parámetro.

// Declare MyTest because operator<< needs it 
template<class T, unsigned int TSIZE> class MyTest; 

// Declare primary template 
template<class T, unsigned int TSIZE> 
inline std::ostream& operator<<(std::ostream& lhs, const MyText<T, TSIZE>& rhs); 

template<class T, unsigned int TSIZE> class MyTest 
{ 
    // Specialization MyTest<T, TSIZE> only declares 
    // specialization operator<< <T, TSIZE> as friend 
    // Note that you can just use '<>' to designate the specialization, 
    // template parameters are deduced from the argument list in this case 
    inline friend std::ostream& operator<< <> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs); 
}; 

La definición que tiene debe coincidir con esas declaraciones. Tenga en cuenta que dado que operator<< es una plantilla, su definición debe estar en el encabezado.

Una alternativa que requiere menos trabajo cuando se trata de escribir todas esas declaraciones preventivas es para MyTest<T, TSIZE> declarar la plantilla completa como un amigo, no solo la especialización que toma MyTest<T, TSIZE>.

// in MyTest definition 
template<typename U, unsigned USIZE> 
inline friend std::ostream& operator<<(std::ostream& lhs, const MyTest<U, USIZE>& rhs); 

La definición tiene también debe coincidir con esa declaración (el nombre de los parámetros de plantilla tiene nada que ver con las declaraciones a juego y definición).

En aras de la exhaustividad, mencionaré que cuando se trata del amigo de una plantilla de clase, una alternativa es definirlo en la definición de plantilla de clase. Esto define una función de amigo sin plantilla que es única para cada especialización.

// in MyTest definition 
friend std::ostream& operator<<(std::ostream& lhs, MyTest const& rhs) 
{ /* implementation */ } 

Es imposible para referirse a tales funciones (por ejemplo &ns::operator<< no funciona, a diferencia de las otras opciones) y se encuentran sólo a través de ADL.

0

No está del todo claro qué quería la publicación original. Voy a suponer que quería lo siguiente:

// Some template class. 
template<class T, unsigned int TSIZE> class MyTest { }; 

// Some template function. 
template<class T, unsigned int TSIZE> std::ostream& operator<< (std::ostream &lhs, const MyTest<T, TSIZE> &rhs) 
{ 
    // IMPLEMENTATION 
} 

Ahora bien, es necesario declarar esta función plantilla como amigo de la clase, porque esta función necesita tener acceso a los objetos protegidos de My test. Esto se puede lograr con la siguiente definición: se necesita

template<class T, unsigned int TSIZE> class MyTest 
{ 
    template<class T1, unsigned int TSIZE1> 
    friend std::ostream& operator<< (std::ostream &lhs, const MyTest<T1, TSIZE1> &rhs); 
}; 

cabecera de la plantilla frente a la declaración friend porque se trata de una función de plantilla no relacionada, que no pertenece a la clase de plantilla actual.

Cuestiones relacionadas