C++ 静态数据成员数组绑定的求值范围

C++ 静态数据成员数组绑定的求值范围,c++,arrays,C++,Arrays,我本来打算针对GCC提交一个bug,但后来意识到,如果我对标准的解释是正确的,那么这是一个核心语言缺陷,而不是编译器bug 当在类范围外定义数组类型的静态数据成员时,将在类范围内查找数组绑定中的标识符 §9.4.2[class.static.data]表示“静态数据成员定义中的初始值设定项表达式在其类(3.3.7)的范围内”,但没有说明声明器本身。这似乎是声明器中唯一的名称查找上下文 §8.4.2[dcl.array]未提及数组绑定的范围,因此默认情况下,表达式在封闭范围(即命名空间)中求值 c

我本来打算针对GCC提交一个bug,但后来意识到,如果我对标准的解释是正确的,那么这是一个核心语言缺陷,而不是编译器bug

当在类范围外定义数组类型的静态数据成员时,将在类范围内查找数组绑定中的标识符

§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 ] = {};
X类{
静态int const size=一些复杂的元函数::值;
静态int-arr[大小];
};
//“size”应限定为“X::size”,这是一种访问冲突。
intx::arr[size]={};
问题是,如果数组绑定没有在类作用域中求值,则无法访问私有类成员,
某些复杂的元函数必须重新指定。数组绑定需要与初始值设定项相同的作用域,原因与初始值设定项基本相同。(虽然没有那么强,因为常量表达式总是可以重新计算的,这与私有对象的地址不同。)


我是缺少什么还是DR正常?

我认为成员定义中绑定的数组在类范围内。标准3.3.7/1:

以下规则描述了类中声明的名称的范围

5) 扩展到或超过类定义结尾的声明的潜在范围也扩展到由其成员定义定义的区域,即使这些成员是在类之外按词汇定义的(这包括静态数据成员定义、嵌套类定义、成员函数定义)(包括成员函数体和声明器部分的任何部分,这些定义遵循声明器id,包括参数声明子句和任何默认参数(8.3.6)


这里的声明符id是
X::arr

在GCC 4.7中
size
X::size
都可以很好地工作。@KerrekSB非常有趣,它也适用于GCC 4.6.1。当您尝试在其他任何地方引用X::size时,您会得到一个编译器错误,但在这里没有问题。您知道这里到底发生了什么吗?哪个编译器错误?
X::size
当然是私有的。@KerrekSB是的,这就是我要针对GCC提出错误的原因:它是有效的,但标准没有规定应该这样做。此外,如果标识符在名称空间和类作用域中有不同的定义,则会选择错误的定义。我不会讨论标准术语,而是原则术语。当您定义一个ethod在类之外,您需要命名它的返回类型,并且可以这样做,即使它是类的
private
。我觉得这里的
X::size
是一样的。从根本上说,定义是类本身的一部分,只是碰巧写在其他地方。嗯,它是否只引用成员函数定义是不明确的。但这涵盖了许多其他情况,例如成员类模板的部分和显式专门化的参数。不平衡的参数加剧了歧义。我认为第二个左参数应该是右参数,在这种情况下,它很好地解释了行为。谢谢!