As we know that we can not initialize a variable in any of the case
in switch
, unless it is the last case
of the respective switch
, as initialization of variables does require the definition to execute at runtime (since the value of the initializer must be determined at that point),
BUT
We also know that a constexpr
variable will get initialized or get replaced in the code with its value during the compilation process itself.
So I tried the below code i.e., initializing a constexpr
variable Z
in case 2
(which is the not the last case
of the switch
) but I am getting an error stating as:
crosses initialization of ‘constexpr const int z’ 24 |
constexpr int z{ 4 }; // illegal: initialization is not allowed if subsequent cases exist
May someone please clarify the reason behind this error?
Thanking you in Advance!
#include <iostream>
int main()
{
switch (1)
{
int y;
case 1:
y = 4;
break;
case 2:
constexpr int z{ 4 }; // ERROR
break;
case 3:
y=5;
break;
}
return 0;
}
CodePudding user response:
According to the c reference for the switch statement
Because transfer of control is not permitted to enter the scope of a variable, if a declaration statement is encountered inside the statement, it has to be scoped in its own compound statement.
This means that you can actually initialize a local variable, constexpr
or not, as long as it is inside a scope. For example, a small modification of your code does compile:
#include <iostream>
int main()
{
switch (1)
{
int y;
case 1:
y = 4;
break;
case 2:
{
constexpr int z{ 4 }; // No more ERROR
break;
}
case 3:
y=5;
break;
}
return 0;
}
Check it live on Coliru.
The switch statement jumps to a matching case
very much like a goto statement
.
Then, like the goto statement, it would be unclear what would happen if, by jumping to a given line, you "skip" the declaration/initialization of the variable.
Consider the following example:
int main()
{
goto jump;
int i = 1;
jump:
}
This does not compile, because in executing the jump, the compiler does not know what to do the variable i. Notice that, if you did not have the jump, it would possible to use the variable i
after the jump
label. But what if you just "skip" the initialization? Then, the code is malformed.
The switch statement, essentially does a goto and because of that it has the same limitations. The fact the the variable you declare is a constexpr
does not change this limitation.
CodePudding user response:
The initialization of a variable with automatic storage duration happens when control transfers over it, regardless of it is a constexpr
variable or not.
Consider the following code (if initializing a constexpr
variable was allowed in the body of a switch
):
void f(const int*);
switch (cond) {
case 1:
constexpr int z{ 4 };
f(&z);
break;
case 2:
f(&z);
break;
}
Even though z
is a constexpr
variable, a compiler would still put it on the stack to pass its address to f
, and it's value on the stack would be assigned 4
at runtime. But what about the case 2
? The compiler will allocate z
on the stack when it enters the switch, but logically the initializer will only be "ran" if it enters the first case.
You can't "initialize" a constexpr
variable at compile time because it will be placed on the stack. Whether it is eliminated entirely and all occurrences of it replaced is an optimization (which isn't always possible if its address is taken).