【问题标题】:Scope of evaluation of array bound of static data member静态数据成员数组绑定的评估范围
【发布时间】: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&lt;&gt;。数组绑定需要与初始化程序相同的范围,原因与初始化程序基本相同。 (虽然没有那么强大,因为常量表达式总是可以重新计算,这与私有对象的地址不同。)

我是否遗漏了什么或者是 DR 是否正常?

【问题讨论】:

  • sizeX::size 在 GCC 4.7 中都能正常工作。
  • @KerrekSB 非常有趣,它也适用于 GCC 4.6.1。当您尝试在其他任何地方引用 X::size 时,您会收到编译器错误,但在这里没问题。你知道这里到底发生了什么吗?
  • 哪个编译器错误? X::size 当然是私人的。
  • @KerrekSB 是的,这就是我要针对 GCC 提交错误的原因:它可以工作,但标准并没有说它应该这样做。此外,如果标识符在命名空间和类范围中有不同的定义,则会选择错误的。
  • 我不会争论标准术语,而是原则性术语。当你在一个类之外定义一个方法时,你需要命名它的返回类型并且可以这样做,即使它是类的private。感觉X::size这里也是一样。从根本上说,定义是类本身的一部分,只是碰巧写在别处。

标签: c++ arrays


【解决方案1】:

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

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

...

5) 延伸到或超过类定义结尾的声明的潜在范围也延伸到由其成员定义定义的区域,即使成员是在类外部按词法定义的(这包括静态数据成员定义,嵌套类定义,成员函数定义(包括成员函数体和此类定义的声明部分的任何部分,遵循声明符ID,包括参数声明子句和任何默认参数( 8.3.6). ...

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

【讨论】:

  • 嗯,这是否仅指成员函数定义是模棱两可的。但这涵盖了许多其他情况,例如成员类模板的部分和显式特化的参数。不平衡的括号加剧了歧义。我认为第二个左括号应该是右括号,在这种情况下,它很好地解释了行为。谢谢!
猜你喜欢
  • 2013-02-16
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多