Reputation: 7369
Consider this example
#include <iostream>
int main(){
switch(int a = 1){ //#condition
case 1: switch(int a = 2){}
case 2: switch(int a = 2){}
}
}
why the redeclarations of a
are well-formed in this example?
According to the following rule:
Names declared in the init-statement, the for-range-declaration, and in the condition of if, while, for, and switch statements are local to the if, while, for, or switch statement (including the controlled statement), and shall not be redeclared in a subsequent condition of that statement nor in the outermost block (or, for the if statement, any of the outermost blocks) of the controlled statement.
IIUC, both the declarations in statement switch(int a = 2){}
or switch(int a = 2){}
are all in the outermost block of the controlled statement which is a compound-statement.
As contrast:
#include <iostream>
int main(){
switch(int a = 1){ //#condition
case 1: int a = 2;
}
}
The redeclaration of a
after case 1
is ill-formed since it's redeclared in the outermost block of that statement.
According to stmt.block, A block is an alias of a compound-statement. So the above rule totally says about block, it's regardless of scope. The rule is equivalent to:
shall not be redeclared in the outermost compound-statement of the controlled statement.
So, what I can't understand here is that, since there's no any block between the condition of inner switch
and the outermost block of the first switch
, how could say that the condition of the inner switch
is not in the outermost block of the outer switch
?
switch(int a = 1){ <- outermost block of the primary `switch`
case 1: switch(int a = 2 /*there's no any block contains this condition*/){}
}
As contrast:
switch(int a = 1){ <- outermost block of the primary `switch`
case 1: { /* here exists a block between `int a = 2` and outermost block of the primary `switch`, so the condition definitely not in the outermost block*/
switch(int a = 2 ){}
}
}
Is there any rule in the standard that I have missed says about the transformation which is similar to stmt.while#2, which will make the condition be contained in an invented block(compound-statement)?
Upvotes: 4
Views: 214
Reputation: 40013
The real question is the meaning of in here. Anything between the {
and }
that delimit the switch
is of course in that “outermost block”, but the use of “outermost” clearly implies that we’re not supposed to consider portions of the program that are (also) inside a nested block. The simplest way to reach that interpretation is to read “in” as “directly in”, in the same sense that “a function declared in a namespace” does not usually include member functions of classes in that namespace. The condition of a nested switch
is then exempt because declarations in it are not directly in any block.
P1787R6, which was adopted in November 2020, clarifies the situation by rewriting [basic.scope.block] to specifically refer to the singular scope associated with the substatement, independently of transformations like that in [stmt.while]/2.
Upvotes: 3
Reputation: 157414
There's no such rule. The code in stmt.while/2 is misleadingly redundant; it could equally be written
label:
if ( condition ) {
statement
goto label ;
}
It is necessary to look at the meaning of the word "in" in stmt.pre/5 and basic.scope.block/3:
Names declared in the init-statement, the for-range-declaration, and in the condition of if, while, for, and switch statements are local to the if, while, for, or switch statement (including the controlled statement), and shall not be redeclared in a subsequent condition of that statement nor in the outermost block (or, for the if statement, any of the outermost blocks) of the controlled statement.
Here, "in" means "immediately in"; it's referring to declaration-statements which would have scope the remainder of the block. Declarations via the condition of a selection statement are not "in" the enclosing block, they are "in" that selection statement.
Upvotes: 0