c++ - 模板类中的模板友元函数
问题描述
在过去已经讨论过实现template friend function
内部 a的问题,template class
并且似乎是标准中未解决的问题,不同编译器的行为不同。
检查gcc和clang的最新可用版本似乎已做出决定,template friend function
要求在.template class
以下代码在使用 -std=c++2a 编译时被最新版本的gcc和clang (gcc x86-64 9.2.0 和 clang x86-64 9.0.0)拒绝。过去的clang版本可以使用它(例如 clang x86-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;
^
是否有关于该主题的新官方决议,或者它只是最新的编译器时尚?
解决方案
我从 CWG 2174 的决议中找出了相关的措辞。它在 C++17 的 [temp.inst]/2 中:
但是,为了根据 [basic.def.odr] 和 [class.mem] 确定实例化的重新声明是否有效,与模板中的定义相对应的声明被认为是定义。
因此,编译器需要将定义的实际实例化推迟到foo
需要存在定义的点(在您的代码中,没有这样的点,因此foo
不实例化),但即使定义未实例化,编译器仍然需要在同一个翻译单元中诊断多个定义,就好像每次实例化声明时都实例化了定义一样。
在我看来,这条规则使得使用友元函数变得不必要地困难,而没有明显的好处,如果在一个类模板中定义的友元函数的多个定义,在同一个 TU 中实例化,被视为一个单一的定义会更好定义。也许,如果我有更多的时间,我会建议对标准进行这样的更改。(是的,我是说我没有时间,所以如果其他人想这样做,请继续,不要担心重复努力。)
除非进行这样的更改,否则您似乎确实需要在类模板之外定义友元函数。
推荐阅读
- json - 如何提高在 Haskell 中使用 JSON 的便利性?
- vue.js - 无法获取 Vuex 突变或操作以将数据传递给状态
- html - 响应式图像代码未获取适当分辨率的图像
- php - 自定义 PHP 添加以集成 Xero
- sql-server - 如何将字符串与从数据库返回的变量连接起来以生成 URL
- android - Android 在哪里存储动态模块 APK?
- bootstrap-4 - 如何在 Bootstrap-4 模态对话框中创建固定位置列
- mysql - 如何编写带有数量单位转换的分组查询SQL?
- arrays - 如何将 2 个相等长度的数组合并到一个带有键的字典中:Godot 中的值对?
- javascript - 当我通过 onchange 事件选择时,我可以在函数外使用变量吗