具有两个参数的模板的c ++友元函数

c++ friend function of template with two parameters

让我有这样的class Foo和它的友元函数::f:

template <typename T>
class Foo {
public:
    template <typename U>
    friend inline void f(Foo<T>, Foo<U>) {}     
};

那我就这样称呼它f(Foo<double>(), Foo<int>()), 谁的朋友 ::f?

只有Foo<double>否则会 也成为 Foo<int> 的朋友,我的意思是 ::f 在声明时成为任何 TFoo<T> 的朋友,或者在使用时编译器生成 ::f 对于 T=double 并发现它是 Foo<double> 的朋友而不是 Foo<int> 的朋友?

如果我这样声明 ::f

template <typename T>
class Foo {
public:
    template <typename U1, typename U2>
    friend inline void f(Foo<U1>, Foo<U2>) {}
};

通话后又成为::f的朋友f(Foo<double>(), Foo<int>());

注意:第二个变种只用clang编译,不是用gcc编译的。

注意如果能看到参考标准的答案就好了。

您没有单一的函数模板 - 您拥有无限大的函数模板。每次实例化Foo<X>,都会定义一个新的函数模板,

template <typename U>
void f(Foo<X>, Foo<U>) {}

此模板的所有实例化都是 Foo<X> 的好友(但不是 U != X 的任何 Foo<U> 的好友)。

因此,当你写 f(Foo<double>(), Foo<int>()) 时, Foo<double>Foo<int> 被实例化,并且用它们定义了 f 的两个重载:

template <typename U>
void f(Foo<double>, Foo<U>) {}

template <typename U>
void f(Foo<int>, Foo<U>) {}

过载解析选择第一个调用(第二个不可行),为U==int实例化。此实例 f<int>(Foo<double>, Foo<int>)Foo<double> 的友元,但不是 Foo<int>


在你的第二个例子中,我相信 gcc 拒绝代码是正确的,而 clang 接受它是错误的(对于它的价值,MSVC 同意 gcc)。 Foo<X> 的每个实例化都将同一模板的定义引入封闭范围:

template <typename U1, typename U2>
void f(Foo<U1>, Foo<U2>) {}

当翻译单元执行两个 Foo 的实例化时,它以两个相同的 f 定义结束,因此出现错误。