在子语句的最外层块中重新声明的变量
The variable redeclared in the outermost block of a substatement
#include <iostream>
int main(){
int b = 2;
if(int a = 0){ // #condition
}else if(b == 2){
int a; //#1
}
}
以上代码在gcc和clang中都可以compiled。但是,根据相关规则的说法,这段代码应该是病式的。规则是:
A name introduced by a declaration in a condition (either introduced by the decl-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is redeclared in the outermost block of a substatement controlled by the condition, the declaration that redeclares the name is ill-formed.
else
后面的 if 语句不是由条件控制的子语句吗? (即只有 #condition
处的条件被执行为 false
才会执行 else
之后的 if 语句)。那么,为什么在这种子语句的最外层块中重新声明名称的声明可以被视为格式正确的代码?
也许n4659
版本的规则中对“由条件控制的子语句”这一短语有一些争论,但是,这样的想法在最新的草案中显然很明确。
A substatement of a statement is one of the following:
for a selection-statement, any of its statements (but not its init-statement)
这意味着 else
之后的语句是主 if-statement
的子语句,那么接下来的规则是:
stmt.stmt#stmt.pre-5
A name introduced in a selection-statement or iteration-statement outside of any substatement is in scope from its point of declaration until the end of the statement's substatements. Such a name cannot be redeclared in the outermost block of any of the substatements
规则显然是说我们不能在这些子语句的最外层块中重新声明与条件中声明的名称相同的名称。所以,我想知道是我误解了这些规则还是草案中存在一些缺陷?
没有
您缺少 else
子语句引入的块作用域:
[stmt.selected.general/2]
: The substatement in a selection-statement (each substatement, in the else
form of the if
statement) implicitly defines a block scope ([basic.scope]). If the substatement in a selection-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original substatement. [..]
即你的代码真的是:
#include <iostream>
int main()
{
int b = 2;
if (int a = 0) {
}
else {
if (b == 2) {
int a;
}
}
}
因此,您正在查看的块(由嵌套 if
引入的块)不是所讨论的“最外层”块。因此,虽然 a
在该块的范围内,但它可以被隐藏。
这个确实意思是you can't declare an a
inside a "naked" else
,即下面是ill-formed:
#include <iostream>
int main()
{
int b = 2;
if (int a = 0) {
}
else {
int a;
}
}
/*
prog.cpp: In function ‘int main()’:
prog.cpp:9:9: error: redeclaration of ‘int a’
int a;
^
prog.cpp:6:11: note: ‘int a’ previously declared here
if (int a = 0) {
*/
stmt.stmt#stmt.pre-5中的语句明确表示:
[Note 2: A name introduced in a selection-statement or iteration-statement outside of any substatement is in scope from its point of declaration until the end of the statement's substatements. Such a name cannot be redeclared in the outermost block of any of the substatements ([basic.scope.block]). — end note]
这里的关键词是outermost block,定义在stmt.block#1:
A compound statement (also known as a block) groups a sequence of statements into a single statement.
compound-statement:
{ statement-seq opt }
...
一个复合语句定义一个块作用域。
所以 stmt.stmt#stmt.pre-5 本质上是在说:
if (int a = 0)
{ // outermost block
int a; // so ill-formed
}
但是
if (int a = 0)
{ // outermost block
{ // inner block
int a; // so well-formed
}
}
相同的规则适用于嵌套 if
语句引入的块的示例。
#include <iostream>
int main(){
int b = 2;
if(int a = 0){ // #condition
}else if(b == 2){
int a; //#1
}
}
以上代码在gcc和clang中都可以compiled。但是,根据相关规则的说法,这段代码应该是病式的。规则是:
A name introduced by a declaration in a condition (either introduced by the decl-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is redeclared in the outermost block of a substatement controlled by the condition, the declaration that redeclares the name is ill-formed.
else
后面的 if 语句不是由条件控制的子语句吗? (即只有 #condition
处的条件被执行为 false
才会执行 else
之后的 if 语句)。那么,为什么在这种子语句的最外层块中重新声明名称的声明可以被视为格式正确的代码?
也许n4659
版本的规则中对“由条件控制的子语句”这一短语有一些争论,但是,这样的想法在最新的草案中显然很明确。
A substatement of a statement is one of the following:
for a selection-statement, any of its statements (but not its init-statement)
这意味着 else
之后的语句是主 if-statement
的子语句,那么接下来的规则是:
stmt.stmt#stmt.pre-5
A name introduced in a selection-statement or iteration-statement outside of any substatement is in scope from its point of declaration until the end of the statement's substatements. Such a name cannot be redeclared in the outermost block of any of the substatements
规则显然是说我们不能在这些子语句的最外层块中重新声明与条件中声明的名称相同的名称。所以,我想知道是我误解了这些规则还是草案中存在一些缺陷?
没有
您缺少 else
子语句引入的块作用域:
[stmt.selected.general/2]
: The substatement in a selection-statement (each substatement, in theelse
form of theif
statement) implicitly defines a block scope ([basic.scope]). If the substatement in a selection-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original substatement. [..]
即你的代码真的是:
#include <iostream>
int main()
{
int b = 2;
if (int a = 0) {
}
else {
if (b == 2) {
int a;
}
}
}
因此,您正在查看的块(由嵌套 if
引入的块)不是所讨论的“最外层”块。因此,虽然 a
在该块的范围内,但它可以被隐藏。
这个确实意思是you can't declare an a
inside a "naked" else
,即下面是ill-formed:
#include <iostream>
int main()
{
int b = 2;
if (int a = 0) {
}
else {
int a;
}
}
/*
prog.cpp: In function ‘int main()’:
prog.cpp:9:9: error: redeclaration of ‘int a’
int a;
^
prog.cpp:6:11: note: ‘int a’ previously declared here
if (int a = 0) {
*/
stmt.stmt#stmt.pre-5中的语句明确表示:
[Note 2: A name introduced in a selection-statement or iteration-statement outside of any substatement is in scope from its point of declaration until the end of the statement's substatements. Such a name cannot be redeclared in the outermost block of any of the substatements ([basic.scope.block]). — end note]
这里的关键词是outermost block,定义在stmt.block#1:
A compound statement (also known as a block) groups a sequence of statements into a single statement.
compound-statement:
{ statement-seq opt }
...
一个复合语句定义一个块作用域。
所以 stmt.stmt#stmt.pre-5 本质上是在说:
if (int a = 0)
{ // outermost block
int a; // so ill-formed
}
但是
if (int a = 0)
{ // outermost block
{ // inner block
int a; // so well-formed
}
}
相同的规则适用于嵌套 if
语句引入的块的示例。