【问题标题】:A template friend function inside a template class模板类中的模板友元函数
【发布时间】:2019-12-19 19:42:18
【问题描述】:

template class 中实现template friend function 的问题在过去已经讨论过,并且似乎是an unresolved issue in the standard 具有不同编译器的不同行为。

检查 gccclang 的最新可用版本,似乎已做出决定,要求 template friend function 的实现在 外部template class

以下代码在编译时被最新版本的 gccclang(gcc x86-64 9.2.0 和 clang x86-64 9.0.0)拒绝-std=c++2a。 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

【问题讨论】:

  • 问题 2174 已在 C++17 中解决:open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2174
  • @NathanOliver 这似乎是答案。它破坏了用于在 clang 中编译的旧代码,但规则是好坏参半的规则:-/
  • @NathanOliver-ReinstateMonica 我不明白这一点。如果问题的解决方案是定义仅在需要定义存在的上下文中引用时才被实例化 - 为什么这意味着 OP 的代码格式错误?我没有看到foo 的任何用法,所以我根本不明白为什么它的定义需要实例化。你能写一个你可以详细说明的答案吗?
  • @Brian 我自己也不确定。我只是指出,上一篇文章中的至少一个问题已经解决。模板实例化规则仍然困扰着我。

标签: c++ templates language-lawyer friend


【解决方案1】:

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

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

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

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

除非进行这样的更改,否则您似乎确实需要在类模板之外定义友元函数。

【讨论】:

    猜你喜欢
    • 2010-12-19
    • 2016-10-19
    • 2013-09-18
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    相关资源
    最近更新 更多