在C++中,为什么不能使用另一个类的模板类型来管理模板类成员函数?

use*_*422 25 c++ templates friend

换句话说,为什么编译正常:

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

class B{
  friend void A<int>::f();
};

template<>
void A<int>::f(){
  B* var = new B();
}
Run Code Online (Sandbox Code Playgroud)

虽然这不是:

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
}
Run Code Online (Sandbox Code Playgroud)

对于第二个代码片段,编译器(gcc 6.2,没有特殊标志)说:

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(){
Run Code Online (Sandbox Code Playgroud)

据我所知,在第二个代码片段中,当声明var时,编译器应该解析B类声明,用int替换友元声明中使用的Type,一切都应该正常工作.我错过了什么?

编辑:下面的评论指出,第二个代码片段似乎与clang和Visual C++ 2015正确编译

Tun*_*gut 4

B<int>使用 before的显式实例化可以A<int>::f()解决此问题。B<int>我假设 GCC 尝试在 的定义中隐式实例化A<int>::f()。但 的定义A<int>::f()尚未完成,GCC“失去”了友元声明。看起来像是编译器问题。

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>();
}
Run Code Online (Sandbox Code Playgroud)