[英]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(Foo<double>(), Foo<int>());
之后又成为::f
朋友
注意:第二个变体仅由 clang 编译,而不是 gcc。
请注意,看到参考标准的答案会很棒。
你没有一个单一的函数模板——你有一个无限的家庭。 每个实例化Foo<X>
都会定义一个新的函数模板,
template <typename U>
void f(Foo<X>, Foo<U>) {}
这个模板的所有实例都是Foo<X>
朋友(但不是任何Foo<U>
for U != X
)。
因此,当您编写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
定义,因此会出现错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.