【问题标题】:What does the standard mean by "a subsequent condition of that statement"?该标准所说的“该陈述的后续条件”是什么意思?
【发布时间】:2015-12-29 05:23:55
【问题描述】:

从 N4567 开始的标准禁止对先前在 条件 中声明的名称进行某些类型的重新声明,如下所示 - 根据标准(§3.3.3/4):

在 for-init-statement、for-range-declaration 以及 if、while、for 和 switch 语句的条件中声明的名称对于 if、while、for 或 switch 语句是局部的(包括受控语句),并且不应在在该语句的后续条件中或在受控语句的最外层块(或者,对于 if 语句,任何最外层块)中重新声明;见 6.4。

但是,考虑到以下代码可以正常编译,

int main(void) {
    if (int i=10)
        if (int i=20)
            ;
    return 0;
}

我似乎不清楚“该语句的后续条件”究竟代表什么。

【问题讨论】:

  • 可能是指for的情况:for(int i = 0; int i = 1;);。在i 的初始声明之后有一个后续条件。 if 的措辞虽然是“任何最外层的块”,但表示它认为 if 的 else 分支是 if 的一部分,所以我认为它也可能指的是 if(int i = 1) ; else if(int i = 1) ;
  • 我认为这是在同一条件下两次声明一个名称。这是两个不同的if 语句,具有不同的条件。
  • 啊,结构是if(...) stmt; else stmt,所以我不认为我的例子与两个ifs匹配。 “任何最外面的块”显然是指if(int i = 1) { int i = 2; } else { int i = 3; },而不是if(int i = 1) ; else if(...) { int i = 2; }(IMO)。
  • @JohannesSchaub-litb 我同意您指出的措辞是用于 for 声明。
  • @Cornstalks 这就是我遇到那段时的想法。确实,它们不属于同一个语句。

标签: c++ language-lawyer


【解决方案1】:

突出显示的“that”语句表示已定义名称的ifwhileforswitch 语句,而不是由条件或迭代控制的子语句。

解释如下:

6.4/3: 由条件中的声明引入的名称(由 decl-specifier-seq 或 条件)在其声明点到结束的范围内 由条件控制的子语句。 如果名字是 在子语句的最外层块中重新声明 条件,重新声明名称的声明格式不正确。

这就是为什么下面的陈述是有效的:

if (int i=10)
    if (int i=20)
        ;

编译器不会将if (int i=20) 的声明分析为同一 if 语句的不同条件,而是作为受控子语句。并且由于 i 的第二次声明发生在条件中,因此在受控语句的外部块中不考虑它。

相比之下,以下几乎等效的语句是无效的,因为它打破了外部块约束:

if (int k=10) {
    int k=20;   // <===== ouch ! redefinition in the outerblock 
    if (k)
        cout <<"oops";
}

因此,您可以拥有“that 语句的后续条件”的唯一情况是 for 语句。该标准突出了这种特殊情况,通过更清晰的措辞为您引用的约束提供了理由:

6.5.3/1: (...) 在 for-init-statement 中声明的名称在同一个声明区域中 作为条件中声明的,

即在 init 和条件中声明相同的名称会破坏 ODR。

【讨论】:

  • 为什么if (int i=20) 不算在子语句的最外层块中重新声明名称?
  • @M.M 因为当您在条件中声明变量时,它在条件和受控语句中可见,但在外部不可见。这就是为什么你不能(不再)重用在 for init 中声明的变量,比如for (int i=...) { ... } if (i==...) handle_special_case();,除非你使用一些编译器上存在的非标准扩展来支持遗留代码。
  • @M.M here an MSDN example of extension 与初始化/条件中定义的变量的有限范围有关
猜你喜欢
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 2021-03-01
  • 2012-12-30
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2016-09-19
相关资源
最近更新 更多