c++ - friends - la declaración de amigo declara una función que no es una plantilla
friend c++> (6)
Esta pregunta ya tiene una respuesta aquí:
Tengo una clase base similar al código a continuación. Estoy intentando sobrecargar << para usar con cout. Sin embargo, g ++ está diciendo:
base.h:24: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, Base<T>*)’ declares a non-template function
base.h:24: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
Intenté agregar <> después de << en la declaración / prototipo de clase. Sin embargo, luego entiendo que does not match any template declaration
. He estado tratando de tener la definición del operador totalmente personalizada (lo que quiero), pero solo he podido hacer que funcione con el siguiente código, con el operador instanciado manualmente.
base.h
template <typename T>
class Base {
public:
friend ostream& operator << (ostream &out, Base<T> *e);
};
base.cpp
ostream& operator<< (ostream &out, Base<int> *e) {
out << e->data;
return out;
}
Solo quiero tener esto o algo similar en el encabezado, base.h:
template <typename T>
class Base {
public:
friend ostream& operator << (ostream &out, Base<T> *e);
};
template <typename T>
ostream& operator<< (ostream &out, Base<T> *e) {
out << e->data;
return out;
}
He leído en otro sitio en línea que poner <> entre << y () en el prototipo debería solucionarlo, pero no es así. ¿Puedo obtener esto en una plantilla de función única?
Gcc te está advirtiendo con razón. A pesar de sus apariencias (toma el argumento Base), no es una plantilla de función.
La definición de su clase tiene una declaración no de plantilla de la función amiga (sin la plantilla), pero la definición de la función amiga más adelante es una plantilla de función (es decir, comienza con la plantilla ...).
También su operador << toma una Base *. Esto no es correcto. Debería ser Base const y retener su semántica incorporada
Probablemente estás viendo algo de la siguiente manera:
template <typename T>
class Base {
public:
friend ostream& operator << (ostream &out, Base<T> const &e){
return out;
};
};
int main(){
Base<int> b;
cout << b;
}
Si quieres tener todas las plantillas, entonces esto es probablemente lo que quieres. Pero no estoy seguro de cuán útil es esto con respecto al anterior. Como la búsqueda implica ADL, nunca podrá resolver ninguna condición en la que T no sea igual a U (siempre que la llamada provenga de un contexto no relacionado con esta clase, por ejemplo, desde la función ''principal'')
template <typename T>
class Base {
public:
template<class U> friend ostream& operator << (ostream &out, Base<U> const &e){
return out;
};
};
int main(){
Base<int> b;
cout << b;
}
Parece que quieres cambiar:
friend ostream& operator << (ostream& out, const Base<T>& e);
A:
template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
Probablemente lo que estás buscando es:
template <typename T>
class Base;
template <typename T>
ostream& operator<< (ostream &, const Base<T>&);
template <typename T>
class Base
{
public:
template<>
friend ostream& operator << <T>(ostream &, const Base<T> &);
};
template <typename T>
ostream& operator<< ( ostream &out, const Base<T>& e )
{
return out << e->data;
}
Estos amigos solo una instanciación única de la plantilla, aquella en la que el parámetro de la plantilla del operador coincide con el parámetro de la plantilla de la clase.
ACTUALIZACIÓN: Desafortunadamente, es ilegal. Tanto MSVC como Comeau lo rechazan. Lo que plantea la pregunta de por qué el mensaje de error original sugiere bastante EXACTAMENTE este enfoque.
cambiando
friend ostream& operator << (ostream &out, Base<T> *e)`
A
template<T> friend ostream& operator << (ostream &out, Base *e)
cambiando
friend ostream& operator << (ostream& out, const Base<T>& e);
a
friend ostream& operator << <T>(ostream& out, const Base<T>& e);
debería funcionar también - Acabo de resolver un problema idéntico de esta manera.
cambio
ostream& operator<< (ostream &out, Base<int> *e) {
out << e->data;
return out;
}
a
ostream& operator<< (ostream &out, T *e) {
out << e->data;
return out;
}