switch
statement
Transfers control to one of several statements, depending on the value of a condition.
Contents |
[edit]Syntax
attr (optional)switch ( init-statement (optional)condition) statement | |||||||||
attr | - | (since C++11) any number of attributes | ||
init-statement | - | (since C++17) any of the following:
Note that any init-statement must end with a semicolon. This is why it is often described informally as an expression or a declaration followed by a semicolon. | ||
condition | - | a condition | ||
statement | - | a statement (typically a compound statement) |
[edit]Condition
A condition can either be an expression or a simple declaration.
| (since C++26) |
- If it can be syntactically resolved as an expression, it is treated as an expression. Otherwise, it is treated as a declaration that is not a structured binding declaration(since C++26).
When control reaches condition, the condition will yield a value, which is used to determine which label the control will go to.
[edit]Expression
If condition is an expression, the value it yields is the the value of the expression.
[edit]Declaration
If condition is a simple declaration, the value it yields is the value of the decision variable (see below).
[edit]Non-structured binding declaration
The declaration has the following restrictions:
- Syntactically conforms to the following form:
| (until C++11) |
| (since C++11) |
- The declarator cannot specify a function or an array.
- The type specifier sequence(until C++11)declaration specifier sequence can only contain type specifiers and constexpr, and it(since C++11) cannot define a class or enumeration.
The decision variable of the declaration is the declared variable.
Structured binding declarationThe declaration has the following restrictions:
The decision variable of the declaration is the invented variable eintroduced by the declaration. | (since C++26) |
[edit]Type
condition can only yield the following types:
- integral types
- enumeration types
- class types
If the yielded value is of a class type, it is contextually implicitly converted to an integral or enumeration type.
If the (possibly converted) type is subject to integral promotions , the yielded value is converted to the promoted type.
[edit]Labels
Any statement within the switch statement can be labeled with one or more following labels:
attr (optional)case constant-expression: | (1) | ||||||||
attr (optional)default: | (2) | ||||||||
attr | - | (since C++11) any number of attributes |
constant-expression | - | a converted constant expression of the adjusted type of the switch condition |
A case or default label is associated with the innermost switch statement enclosing it.
If any of the following conditions is satisfied, the program is ill-formed:
- A switch statement is associated with multiple case labels whose constant-expression s have the same value after conversions.
- A switch statement is associated with multiple default labels.
[edit]Control flow transfer
When the condition of a switch statement yields a (possibly converted) value:
- If one of the associated case label constants has the same value, control is passed to the statement labeled by the matched case label.
- Otherwise, if there is an associated default label, control is passed to the statement labeled by the default label.
- Otherwise, none of the statements in the switch statement will be executed.
case and default labels in themselves do not alter the flow of control. To exit from a switch statement from the middle, see break statements.
Compilers may issue warnings on fallthrough (reaching the next case or default label without a break) unless the attribute [[fallthrough]]
appears immediately before the case label to indicate that the fallthrough is intentional(since C++17).
switch statements with initializerIf init-statement is used, the switch statement is equivalent to
Except that names declared by the init-statement (if init-statement is a declaration) and names declared by condition (if condition is a declaration) are in the same scope, which is also the scope of statement. | (since C++17) |
[edit]Notes
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:
[edit]Keywords
[edit]Example
The following code shows several usage cases of the switch statement:
#include <iostream> int main(){constint i =2;switch(i){case1:std::cout<<'1';case2:// execution starts at this case labelstd::cout<<'2';case3:std::cout<<'3';[[fallthrough]];// C++17 attribute to silent the warning on fallthroughcase5:std::cout<<"45";break;// execution of subsequent statements is terminatedcase6:std::cout<<'6';} std::cout<<'\n'; switch(i){case4:std::cout<<'a';default:std::cout<<'d';// there are no applicable constant expressions // therefore default is executed} std::cout<<'\n'; switch(i){case4:std::cout<<'a';// nothing is executed} // when enumerations are used in a switch statement, many compilers// issue warnings if one of the enumerators is not handledenum color { RED, GREEN, BLUE };switch(RED){case RED:std::cout<<"red\n";break;case GREEN:std::cout<<"green\n";break;case BLUE:std::cout<<"blue\n";break;} // the C++17 init-statement syntax can be helpful when there is// no implicit conversion to integral or enumeration typestruct Device {enum State { SLEEP, READY, BAD };auto state()const{return m_state;} /* ... */ private: State m_state{};}; switch(auto dev = Device{}; dev.state()){case Device::SLEEP:/* ... */break;case Device::READY:/* ... */break;case Device::BAD:/* ... */break;} // pathological examples // the statement does not have to be a compound statementswitch(0)std::cout<<"this does nothing\n"; // labels do not require a compound statement eitherswitch(int n =1)case0:case1:std::cout<< n <<'\n';}
Output:
2345 d red 1
[edit]Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1767 | C++98 | condition s of types that are not subject to integral promotion could not be promoted | do not promote condition s of these types |
CWG 2629 | C++98 | condition could be a declaration of a floating-point variable | prohibited |
[edit]See also
C documentation for switch |
[edit]External links
1. | Loop unrolling using Duff's Device |
2. | Duff's device can be used to implement coroutines in C/C++ |