我偶然发现g ++(5.2.0)编译了以下内容
template<typename T>
struct A {
int x;
struct B {
void foo() {
x = 1;
}
};
};
如果未使用成员A
,即使是A::B
和B::foo
正在发布。即使只是编译no-op语句x
,你也可以合理地得到A
作为&A<int>::B::foo;
的非静态成员的编译错误。
clang(3.6.2)拒绝模板,即使A
没有实例化,因为它表示在x
内不能使用非静态成员名B
只是阅读模板定义。
这是g ++或clang中的错误对未实例化的模板成员过于严格吗?
答案 0 :(得分:2)
代码中的x
是一个非依赖名称,并且标准呈现的模板无法有效地实例化,无论您提供什么样的模板参数都是错误的,不需要诊断(实际上这也适用于“temploids”,作为标准显示的一个例子。也就是说,规则同样适用于类模板的成员。)
您的代码与访问周围类名称的任何普通类一样无效。请注意,方向在这里很重要。以下不格式不正确(因为可以专门化A<T>::B
,x
A<int>::B
是静态成员,例如。
template<typename T>
struct A {
struct B {
int x;
};
void f() {
B::x = 1;
}
};
但是,包含类模板的类型称为当前实例化,这意味着它的含义始终保持不变,并且根据模板参数不能更改。因此,模板定义本身可能会因某些用途(如您的用途)而变得格式不正确。
答案 1 :(得分:1)
[temp.res] / 8说:
没有诊断 应为可以生成有效专业化的模板颁发。如果没有有效的专业化可以 为模板生成,并且该模板未实例化,模板格式错误,无法诊断 必需的。
我认为第二句适用于B
的未使用部分。如果函数未实例化,则编译器不需要意识到它无法实例化。