1

Is it correct to use constexpr variable as a case label.

#include <iostream>

int main() {
    constexpr int x = 5;

    int y = 4;

    switch (y) {
        case x - 1:
            std::cout << "case " << x << std::endl;

            break;

        case 20:
            std::cout << "case 20" << std::endl;

            break;

        default:
            std::cout << "case default" << std::endl;

            break;
    }
}
Aamir
  • 1,974
  • 1
  • 14
  • 18
Harry
  • 2,177
  • 1
  • 19
  • 33
  • Have you tried it? Why it would not be correct? – Phil1970 Jun 30 '23 at 12:12
  • 2
    It is "correct" in that it is allowed by the C++ standard, just as `case 4 - 1:` is allowed. Probably will cause confusion to whoever has to maintain that code. – Eljay Jun 30 '23 at 12:12
  • Have you tried it? With multiple compilers? [The compiler explorer](https://godbolt.org) is a good platform for experiments like that. If all the major compilers agree, then it it can probably be trusted. – Some programmer dude Jun 30 '23 at 12:13
  • This doesn't address the question, but the code here doesn't need the extra stuff that `std::endl` does. `'\n'` ends a line. – Pete Becker Jun 30 '23 at 12:14
  • @Eljay Not necessarily confusion, there are cases you even cannot do otherwise. Or how would you want to handle the result of a `WaitForMultipleObjects` or `WSAWaitForMultipleEvents` call (well, they have `#define`s, as C, but still...)? Admitted, posix has far superior interface with `poll`, but that's how the world is on Windows ;) – Aconcagua Jun 30 '23 at 12:20
  • A very nice use case of this is to do switch/case for string constants as explained in [this answer](https://stackoverflow.com/a/16388610/11993121). – nielsen Jun 30 '23 at 12:32
  • As example of confusion, there is the display of `x` for the `case x-1` ;-) – Jarod42 Jun 30 '23 at 12:38

1 Answers1

8

It is. cppreference says the case value must be

a constant expression of the same type as the type of condition after conversions and integral promotions

That includes constexpr expressions like a constexpr variable to which you subtract 1 like in your example.

In the standard, that's [stmt.switch]:

Any statement within the switch statement can be labeled with one or more case labels as follows:
case constant-expression :
where the constant-expression shall be a converted constant expression of the adjusted type of the switch condition. No two of the case constants in the same switch shall have the same value after conversion.

And a constant expression is anything in [expr.const].

For example, you can even use a constexpr function call:

constexpr int caseLabel() {
    return 4;
}
// ...
switch (y) {
    case caseLabel():
Nelfeal
  • 12,593
  • 1
  • 20
  • 39