【问题标题】:Template friendship error compilation with GCC but not with clang使用 GCC 但不使用 clang 的模板友谊错误编译
【发布时间】:2016-04-07 08:15:01
【问题描述】:

此代码使用 clang 3.7.1 编译(没有诊断)但使用 GCC 5.3.0失败> (live example):

#include <iostream>

template<typename T>
struct A {
    void foo()
    {
        static_cast<T*>(this)->implementation();
    }
};

struct Crtp : A<Crtp> {
    template<typename T>
    friend struct A;
private:
    void implementation() { std::cout << "implementation()\n"; }
};

int main()
{
    Crtp c;
    c.foo();
}

GCC的错误信息如下:

main.cpp:13:16: 错误:实例化后“A”的特化 朋友结构A;

哪一个是对的,为什么?是不是 GCC/clang 的 bug?

【问题讨论】:

    标签: c++ gcc clang friend crtp


    【解决方案1】:

    似乎是一个旧的 g++ 错误 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52625)。

    如果我理解正确,已报告且从未更正,

    【讨论】:

    【解决方案2】:

    我认为这是 gcc 的错误。

    模板友元类声明只是一个声明,而不是一个定义。 允许重新声明类模板,除非它具有不同的 class-key(参见 N4527 14.5.1.4)。

    专业化或实例化可以发生两次或更多次。 显式特化只能发生一次 (N4527 14.7.3.6)。

    然后,gcc 的诊断很奇怪,因为没有明确的专业化。

    【讨论】:

      【解决方案3】:

      我们确实有一些模板名称解析的可能性:

      struct Crtp : A<Crtp> {
        A x; // A refers to A<Crtp>
      };
      

      现在一切都清楚了:

      template<typename T> friend struct A; 
      

      指:

      template<typename T> friend struct A<Crtp>; 
      

      这是......是的,部分专业化(真的很棘手)。

      所以 GCC 在这里是正确的。

      你真正需要的是:

      struct Crtp : A<Crtp> {
      friend struct A;
      private:
          void implementation() { std::cout << "implementation()\n"; }
      };
      

      【讨论】:

        猜你喜欢
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-24
        • 2017-10-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多