此代码使用 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的错误吗?
答案 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"; }
};