switch
statement
条件の値に応じて、複数の文のいずれかに制御を転送します。
目次 |
構文
attr
(オプション)
switch
(
init-statement
(オプション)
condition
)
statement
|
|||||||||
| attr | - | (since C++11) 任意の数の 属性 | ||
| init-statement | - |
(since C++17)
以下のいずれか:
任意の init-statement はセミコロンで終了する必要があることに注意。これが、しばしば非公式に「式または宣言の後にセミコロンが続くもの」と説明される理由である。 |
||
| condition | - | 条件 | ||
| statement | - | 文(通常は複文) |
条件
condition は、 expression または simple declaration のいずれかです。
|
(C++26以降) |
- 構文的に式として解決できる場合は、式として扱われます。それ以外の場合は、構造化束縛宣言ではない宣言として扱われます (since C++26) (C++26以降) 。
`, `
`, `
制御が条件に到達すると、条件は値を生成し、その値を使用して制御がどのラベルに進むかを決定します。
式
condition が式である場合、それが生成する値はその式の値となります。
宣言
condition が単純な宣言である場合、それが生成する値は決定変数の値となります(下記参照)。
非構造化バインディング宣言
この宣言には以下の制限があります:
- 構文的には以下の形式に従います:
|
(C++11まで) |
|
(C++11以降) |
- 宣言子は 関数 または 配列 を指定できません。
- 型指定子シーケンス (C++11まで) 宣言指定子シーケンス は型指定子と constexpr のみを含むことができ、 (C++11以降) クラス または 列挙型 を定義できません。
宣言の決定変数は、宣言された変数です。
構造化バインディング宣言この宣言には以下の制限があります:
この宣言の決定変数は、宣言によって導入される発明された変数 e です 。 |
(C++26以降) |
型
condition は以下の型のみを生成できます:
- 整数型
- 列挙型
- クラス型
生成された値がクラス型の場合、文脈的に整数型または列挙型へ暗黙的に変換されます。
もし(変換された可能性のある)型が 整数プロモーション の対象となる場合、生成された値はプロモーション後の型に変換されます。
ラベル
switch 文内の任意のステートメントには、以下のラベルの1つ以上を付けることができます:
attr
(オプション)
case
constant-expression
:
|
(1) | ||||||||
attr
(オプション)
default:
|
(2) | ||||||||
| attr | - | (C++11以降) 任意の数の 属性 |
| constant-expression | - | 変換済み定数式 で、 switch 条件の調整された型のもの |
A
case
または
default
ラベルは、それを囲む最も内側の
switch
文に関連付けられます。
以下のいずれかの条件が満たされる場合、プログラムは不適格となります:
- switch 文が、変換後の constant-expression の値が同じ複数の case ラベルに関連付けられている。
- switch 文が複数の default ラベルに関連付けられている。
制御フローの転送
switch 文の条件が(変換された可能性のある)値を返す場合:
- 関連付けられた case ラベル定数の1つが同じ値を持つ場合、制御は一致した case ラベルで指定された文に移ります。
- それ以外の場合、関連付けられた default ラベルが存在するならば、制御は default ラベルで指定された文に移ります。
- それ以外の場合、 switch 文内のどの文も実行されません。
case および default ラベル自体は制御フローを変更しません。 switch 文の途中から抜け出すには、 break 文 を参照してください。
コンパイラはフォールスルー(break文なしで次の
case
または
default
ラベルに到達すること)に対して警告を発することがある
。ただし、属性
[[
fallthrough
]]
が
case
ラベルの直前に記述されている場合は、そのフォールスルーが意図的であることを示す
(C++17以降)
。
|
switch 初期化子付きswitch文init-statement が使用される場合、switch文は以下と等価である:
ただし、 init-statement によって宣言された名前( init-statement が宣言である場合)および condition によって宣言された名前( condition が宣言である場合)は同じスコープにあり、これは statement のスコープでもある。 |
(C++17以降) | |||||||||||||||||||||||
注記
制御の転送が変数のスコープに 入ることが許可されていない ため、宣言文が statement 内で見つかった場合、独自の複合文内でスコープされなければなりません:
キーワード
例
以下のコードは switch 文のいくつかの使用例を示しています:
#include <iostream> int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // 実行はこのcaseラベルから開始 std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // C++17のフォールスルー警告を抑制する属性 case 5: std::cout << "45"; break; // 以降の文の実行は終了 case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // 該当する定数式がないため // defaultが実行される } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; // 何も実行されない } // 列挙型がswitch文で使用される場合、多くのコンパイラは // 列挙子の1つが処理されていない場合に警告を発行する enum 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; } // C++17の初期化文構文は、整数型または列挙型への暗黙的な変換が // ない場合に有用である struct 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; } // 病理学的な例 // 文は複合文である必要はない switch (0) std::cout << "this does nothing\n"; // ラベルも複合文を必要としない switch (int n = 1) case 0: case 1: std::cout << n << '\n'; }
出力:
2345 d red 1
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 1767 | C++98 |
condition
のうち整数昇格の対象とならない型のものは
昇格できなかった |
これらの型の
condition
は
昇格しない |
| CWG 2629 | C++98 | condition が浮動小数点変数の宣言となりえた | 禁止 |
関連項目
|
Cドキュメント
の
switch
|
外部リンク
| 1. | ダフのデバイスを使用したループ展開 |
| 2. | ダフのデバイスはC/C++でコルーチンを実装するために使用できる |