模板友谊错误编译与GCC但不与clang

时间:2016-04-07 08:15:02

标签: c++ gcc clang friend crtp

此代码使用 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的错误吗?

3 个答案:

答案 0 :(得分:4)

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

如果我理解正确,报告并且从未纠正过,

答案 1 :(得分:3)

我认为这是gcc的错误。

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

专业化或实例化可以发生两次或更多次。 明确的专业化只能发生一次(N4527 14.7.3.6)。

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

答案 2 :(得分:0)

我们确实有一些模板名称解析赔率:

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"; }
};