繁体   English   中英

模板类中的模板友元函数

[英]A template friend function inside a template class

template class中实现template friend function问题在过去已经讨论过,并且在标准中似乎是一个未解决的问题,不同编译器的行为不同。

检查gcc铿锵的最新可用版本似乎作出决定,要求执行template friend function外部template class

以下代码在使用 -std=c++2a 编译时被最新版本的gccclang (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;    
         ^

是否有关于该主题的新官方决议,还是只是最新的编译器时尚?

https://godbolt.org/z/ySrVe3

我从 CWG 2174 的决议中找出了相关的措辞。它在 C++17 中的 [temp.inst]/2 中:

但是,为了根据 [basic.def.odr] 和 [class.mem] 确定实例化的重新声明是否有效,与模板中的定义相对应的声明被认为是定义。

因此,编译器需要推迟定义的实际实例化,直到需要存在foo定义的点(在您的代码中,没有这样的点,因此foo不会被实例化),但即使定义是未实例化,编译器仍然需要诊断同一翻译单元中的多个定义,就像每次实例化声明时都已实例化定义一样。

在我看来,这条规则使得在没有明显好处的情况下使用友元函数变得不必要地困难,如果在同一个 TU 中实例化的类模板中定义的友元函数的多个定义被视为单个定义。 也许,如果我有更多的时间,我会建议对标准进行这样的更改。 (是的,我是说我没有时间,所以如果其他人想这样做,请继续,不要担心重复工作。)

除非做出这样的改变,看起来你确实需要在类模板之外定义友元函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM