模板类中的模板友元函数
A template friend function inside a template class
在template class
中实现template friend function
的问题过去已经讨论过,并且在标准中似乎是一个未解决的问题,具有不同编译器的不同行为。
检查gcc和clang的最新可用版本似乎已做出决定,要求template friend function
的实施在template class
之外。
当使用 -std=c++2a 编译时,最新版本的 gcc 和clang(gccx86-64 9.2.0 和 clang x86-64 9.0.0(拒绝以下代码。 过去的 clang 版本都可以(例如clangx86-64 7.0.0(。
template<long Num>
struct A {
template<long Num1, long Num2>
friend int foo(A<Num1> a1, A<Num2> a2) {
return 1;
}
// the compilation error occurs only with a template friend function
// and only if *implemented inside* a template class
};
int main() {
A<1> a1;
A<2> a2; // commenting this line removes the error
}
两个编译器都抱怨对foo的重新定义:
<source>:4:16: error: redefinition of 'foo'
friend int foo(A<Num1> a1, A<Num2> a2) {
^
<source>:11:10: note: in instantiation of template class 'A<2>' requested here
A<2> a2;
^
是否有关于该主题的新官方决议,或者它只是最新的编译器时尚?
https://godbolt.org/z/ySrVe3
我从CWG 2174的决议中找出了相关措辞。它在 C++17 中的 [temp.inst]/2 中:
但是,为了根据 [basic.def.odr] 和 [class.mem] 确定实例化的重新声明是否有效,与模板中的定义对应的声明被视为定义。
因此,编译器需要将定义的实际实例化推迟到需要存在foo
定义的点(在您的代码中,没有这样的点,因此不会实例化foo
(,但即使定义未实例化,编译器仍然需要诊断同一转换单元中的多个定义,就好像每次实例化声明时都实例化了定义一样。
在我看来,这条规则使得使用友元函数变得不必要地困难,而没有明显的好处,如果将类模板中定义的友元函数的多个定义(在同一 TU 中实例化(视为单个定义会更好。也许,如果我有更多的时间,我会建议对标准进行这样的更改。(是的,我说我没有时间,所以如果其他人想这样做,请继续,不要担心重复工作。
除非进行这样的更改,否则实际上似乎确实需要在类模板之外定义 friend 函数。
- C++模板来检查友元函数的存在
- 如何使用单独文件中的派生类访问友元函数对象
- 模板化的类和友元函数
- 友元函数无法访问私有数据成员 (c++)
- 继承和友元函数,从基类访问受保护的成员
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 在模板类之外定义友元函数的正确方法是什么?
- 2个模板化类的非模板友元函数未定义引用错误
- C++ 友元函数和私有构造函数
- 使第二个类的构造函数成为第一个类中的友元函数
- 未定义的类模板不会实例化以检查友元函数
- C++类中的友元函数有问题?
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 模板类中的模板友元函数
- C++ 17 个友元函数声明和内联命名空间
- 友元函数需要一个帮助程序函数
- 在类内定义的友元函数与类外定义的友元函数的查找规则之间的差异
- 运算符重载在 C++ 中使用友元函数
- 类C++友元函数无法访问封装的类
- 函数指针作为友元函数