tipos sirven que plantillas para los funciones c++ templates friend

sirven - En C++, ¿por qué no es posible crear una función de miembro de clase de plantilla mediante el tipo de plantilla de otra clase?



plantillas en c++ (2)

En otras palabras, ¿por qué esto compila bien?

template<typename Type> class A{ public: void f(); }; class B{ friend void A<int>::f(); }; template<> void A<int>::f(){ B* var = new B(); }

Mientras que esto no lo hace:

template<typename Type> class A{ public: void f(); }; template<typename Type> // B is now a templated class class B{ friend void A<Type>::f(); // Friending is done using B templated type }; template<> void A<int>::f(){ B<int>* var = new B<int>(); // var is now declared using int as its templated type }

Para el segundo fragmento de código, el compilador (gcc 6.2, sin indicadores especiales) dice:

main.cpp: In instantiation of ‘class B<int>’: main.cpp:14:28: required from here main.cpp:9:15: error: prototype for ‘void A<int>::f()’ does not match any in class ‘A<int>’ friend void A<Type>::f(); ^~~~~~~ main.cpp:13:6: error: candidate is: void A<Type>::f() [with Type = int] void A<int>::f(){

Como lo entiendo, en el segundo fragmento de código, al declarar var, el compilador debería analizar la declaración de clase B, reemplazar el Tipo usado en la declaración de amigo por int, y todo debería funcionar bien. ¿Qué me estoy perdiendo?

EDITAR: los comentarios a continuación han señalado que el segundo fragmento de código parece compilar correctamente con Clang y Visual C ++ 2015


La especialización de la función miembro de la template class sin la especialización de template class completa es un caso especial cuando se le permite especializarse en la función de miembro no de la template , por lo que tal vez GCC está confundido y no conozco los motivos, pero de alguna manera no puede declarar amistad a los especialistas miembro no de template class de template class . La solución temporal sería especializar class template para que esto funcione.

//class template A template<typename Type> class A{ public: void f(); }; //class A<int> template<> class A<int>{ public: void f(); };

Luego, define A<int>::f :

Para la class B:

void A<int>::f(){ B* var = new B(); (void)(var); }

Para la template class B :

void A<int>::f(){ B<int>* var = new B<int>(); (void)(var); }

Pero creo que Clang está aquí, no debería haber problemas para tal declaración de amigo. Es probable que sea un error en GCC .


Una creación de instancias explícita de B<int> antes de que se use en A<int>::f() resuelve este problema. Supongo que GCC intenta una creación de instancias implícita de B<int> en la definición de A<int>::f() . Pero la definición de A<int>::f() no está terminada y GCC ''pierde'' la declaración de amigo. Parece un problema de compilación.

template<typename Type> class A { public: void f(); }; template<typename Type> // B is now a templated class class B { friend void A<Type>::f(); // Friending is done using B templated type }; template class B<int>; // <= explicit instantiation, that works template<> void A<int>::f() { B<int>* var = new B<int>(); }