【发布时间】:2012-04-08 10:38:28
【问题描述】:
我打算向 GCC 提交一个错误,但后来意识到如果我对标准的解释是正确的,那是核心语言缺陷,而不是编译器错误。
当数组类型的静态数据成员在类范围之外定义时,数组绑定中的标识符在类范围内查找。
§9.4.2 [class.static.data] 说“静态数据成员定义中的初始化表达式在其类 (3.3.7) 的范围内”,但没有说明声明符本身。这似乎是声明器中唯一的名称查找上下文。
§8.4.2 [dcl.array] 没有提及数组绑定的范围,因此默认情况下,表达式在封闭范围内进行计算,即命名空间。
class X {
static int const size = some_complicated_metafunction<>::value;
static int arr[ size ];
};
// "size" should be qualified as "X::size", which is an access violation.
int X::arr[ size ] = {};
问题在于,如果数组绑定没有在类范围内求值,则无法访问私有类成员,并且必须重新指定 some_complicated_metafunction<>。数组绑定需要与初始化程序相同的范围,原因与初始化程序基本相同。 (虽然没有那么强大,因为常量表达式总是可以重新计算,这与私有对象的地址不同。)
我是否遗漏了什么或者是 DR 是否正常?
【问题讨论】:
-
size和X::size在 GCC 4.7 中都能正常工作。 -
@KerrekSB 非常有趣,它也适用于 GCC 4.6.1。当您尝试在其他任何地方引用 X::size 时,您会收到编译器错误,但在这里没问题。你知道这里到底发生了什么吗?
-
哪个编译器错误?
X::size当然是私人的。 -
@KerrekSB 是的,这就是我要针对 GCC 提交错误的原因:它可以工作,但标准并没有说它应该这样做。此外,如果标识符在命名空间和类范围中有不同的定义,则会选择错误的。
-
我不会争论标准术语,而是原则性术语。当你在一个类之外定义一个方法时,你需要命名它的返回类型并且可以这样做,即使它是类的
private。感觉X::size这里也是一样。从根本上说,定义是类本身的一部分,只是碰巧写在别处。