我打算提交一个针对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?
答案 0 :(得分:4)
我认为成员定义中绑定的数组在类范围内。标准3.3.7 / 1:
以下规则描述了在类中声明的名称范围。
...
5)扩展到或超过类定义结尾的声明的潜在范围也扩展到由其成员定义定义的区域,即使成员是在类之外的词法上定义的(这包括静态数据成员定义) ,嵌套类定义,成员函数定义(包括成员函数体和此类定义的声明器部分的任何部分,遵循declarator-id ,包括parameter-declaration-clause和任何默认参数( 8.3.6)。...
此处声明者ID为X::arr
。