具有两个参数的模板的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
在声明时成为任何 T
的 Foo<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
定义结束,因此出现错误。
让我有这样的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
在声明时成为任何 T
的 Foo<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
定义结束,因此出现错误。