模板好友功能的前向声明

Can*_*ame 8 c++ templates friend

请考虑以下完全正常的代码片段:

class A
{
private:
    int d;
public:
    A(int n){ d = n;}
    friend int foo(A a);
};

int foo(A a)
{
    return a.d;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试为类使用模板时,我需要转发声明友元函数才能运行,如下所示:

template <typename T>
class B;

template <typename T>
T foof(B<T> a);


template <typename T>
class B
{
private:
    T d;
public:
    B(T n){ d = n;}
    friend T foof<>(B<T> a);
};

template <typename T>
T foof(B<T> a)
{
    return a.d;
}
Run Code Online (Sandbox Code Playgroud)

为什么前面的声明在第二个例子中是必要的而不是在第一个例子中?另外,为什么我必须<>在B类中加入foof声明?为什么在模板内声明它是不够的?我试图理解这些东西是如何工作的,所以当我需要使用它时,我不必盲目地记住这种代码.

谢谢

xin*_*aiz 7

那是因为

friend int foo(A a);
Run Code Online (Sandbox Code Playgroud)

是功能声明和朋友同时,但是:

friend T foof<>(B<T> a);
Run Code Online (Sandbox Code Playgroud)

是模板实例化的朋友声明.那不一样.实例化不声明模板功能.


你可以成为整个函数模板的朋友,然后不需要转发声明:

template <typename T>
class B
{
private:
    T d;
public:
    B(T n){ d = n;}
    template<class U>
    friend U foof(B<U> a);
};
Run Code Online (Sandbox Code Playgroud)

  • 注意:后者可能会产生意想不到的后果。它表示,对于任何给定的“T”,我们都会将“foof”的*所有*实例化为好友,无论“T”是否是模板参数。简而言之,“int foof&lt;int&gt;(B&lt;int&gt;);”是“B&lt;double&gt;”的友元。在采用对模板函数(或类)的所有实例进行全面友好的焦土方法之前,请考虑这是否是一个问题。 (2认同)