In other words, why does this compile fine :
template<typename Type>
class A{
public:
void f();
};
class B{
friend void A<int>::f();
};
template<>
void A<int>::f(){
B* var = new B();
}
While this doesn't :
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
}
For the second code snippet, compiler (gcc 6.2, no special flags) says:
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(){
As I understand it, in the second code snippet, when declaring var the compiler should parse B class declaration, replace the Type used in the friend declaration by int, and everything should work fine. What am I missing?
EDIT : comments below have pointed out that the second code snippet seems to compile correctly with clang and Visual C++ 2015
An explicit instantiation of B<int>
before it is used in A<int>::f()
resolves this problem. I assume GCC tries an implicit instantiation of B<int>
in the definition of A<int>::f()
. But the definition of A<int>::f()
is not finished and GCC 'looses' the friend declaration. It looks like a compiler problem.
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>();
}