Home > Back-end >  Why can't we initialize a "constexpr variable" inside a Switch (below a non last SWIT
Why can't we initialize a "constexpr variable" inside a Switch (below a non last SWIT

Time:12-22

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).

  • Related