使用 GCC 编译模板友谊错误,但不使用 clang
Template friendship error compilation with GCC but not with clang
此代码使用 clang 3.7.1(没有诊断)编译,但因 GCC[=23 而失败=] 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: error: specialization of 'A' after instantiation
friend struct A;
哪一个是正确的,为什么?是 GCC / clang 的错误吗?
我认为这是 gcc 的错误。
A template friend class 声明只是声明,不是定义。
允许重新声明 class 模板,除非它具有不同的 class-key(参见 N4527 14.5.1.4)。
特化或实例化可以发生两次或更多次。
显式专业化只能发生一次(N4527 14.7.3.6)。
然后,gcc 的诊断很奇怪,因为没有明确的专门化。
似乎是一个旧的 g++ 错误 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52625)。
已举报,未更正,如果我理解正确,
我们确实有一些模板名称解析几率:
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"; }
};
此代码使用 clang 3.7.1(没有诊断)编译,但因 GCC[=23 而失败=] 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: error: specialization of 'A' after instantiation friend struct A;
哪一个是正确的,为什么?是 GCC / clang 的错误吗?
我认为这是 gcc 的错误。
A template friend class 声明只是声明,不是定义。 允许重新声明 class 模板,除非它具有不同的 class-key(参见 N4527 14.5.1.4)。
特化或实例化可以发生两次或更多次。 显式专业化只能发生一次(N4527 14.7.3.6)。
然后,gcc 的诊断很奇怪,因为没有明确的专门化。
似乎是一个旧的 g++ 错误 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52625)。
已举报,未更正,如果我理解正确,
我们确实有一些模板名称解析几率:
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"; }
};