switch 文
条件の値に応じて、複数の文のいずれかに制御を移します。
目次 |
[編集] 構文
attr (オプション) switch ( init-statement (オプション) condition ) statement |
|||||||||
| attr | - | (C++11以降) 任意の数の属性 | ||
| init-statement | - | (C++17 以降) 以下のいずれか
どのinit-statementもセミコロンで終わらなければならないことに注意してください。これが、しばしば非公式に式または宣言の後にセミコロンが続くと説明される理由です。 | ||
| condition | - | 条件 | ||
| statement | - | 文 (通常は複合文) |
[編集] 条件
|
(C++26以降) |
- 構文的に式として解決できる場合、式として扱われます。それ以外の場合は、宣言(構造化束縛宣言ではない)(C++26以降)として扱われます。
制御が条件に到達すると、条件は値を生成し、その値を使用して制御がどのラベルに移動するかを決定します。
[編集] 式
condition が式の場合、生成される値はその式の値です。
[編集] 宣言
condition が単純宣言の場合、生成される値は決定変数 (下記参照) の値です。
[編集] 非構造化束縛宣言
宣言には以下の制限があります
- 構文的に以下の形式に準拠します
|
(C++11まで) |
|
(C++11以降) |
宣言の判定変数は、宣言された変数です。
構造化束縛宣言宣言には以下の制限があります
宣言の判定変数は、宣言によって導入される発明された変数eです。 |
(C++26以降) |
[編集] 型
condition は以下の型のみを生成できます。
- 整数型
- 列挙型
- クラス型
生成された値がクラス型の場合、それは文脈的に暗黙的に整数型または列挙型に変換されます。
(変換された可能性のある) 型が整数昇格の対象となる場合、生成された値は昇格された型に変換されます。
[編集] ラベル
switch 文内の任意の文には、以下の1つ以上のラベルを付けることができます。
attr (オプション) case constant-expression : |
(1) | ||||||||
attr (オプション) default: |
(2) | ||||||||
| attr | - | (C++11以降) 任意の数の属性 |
| 定数式 | - | switch 条件の調整された型の変換された定数式 |
case または default ラベルは、それを囲む最も内側の switch 文に関連付けられます。
以下のいずれかの条件が満たされる場合、プログラムは不適格です。
- switch 文が、変換後に同じ値を持つ constant-expression を持つ複数の case ラベルに関連付けられている場合。
- switch 文が、複数の default ラベルに関連付けられている場合。
[編集] 制御フローの転送
switch 文の条件が (変換された可能性のある) 値を生成するとき
- 関連付けられた case ラベル定数のいずれかが同じ値を持つ場合、制御は一致する case ラベルでラベル付けされた文に渡されます。
- そうでない場合、関連付けられた default ラベルがある場合、制御は default ラベルでラベル付けされた文に渡されます。
- そうでない場合、switch 文内のどの文も実行されません。
case および default ラベル自体は制御フローを変更しません。switch 文の途中から抜けるには、break 文を参照してください。
コンパイラは、フォールスルー ( break なしで次の case または default ラベルに到達すること) について警告を発することがあります。ただし、フォールスルーが意図的であることを示すために、属性 [[fallthrough]] が case ラベルの直前に現れる場合は除きます(C++17 以降)。
|
初期化子付き 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: // execution starts at this case label std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // C++17 attribute to silent the warning on fallthrough case 5: std::cout << "45"; break; // execution of subsequent statements is terminated case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // there are no applicable constant expressions // therefore default is executed } std::cout << '\n'; switch (i) { case 4: 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 handled 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; } // the C++17 init-statement syntax can be helpful when there is // no implicit conversion to integral or enumeration type 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; } // pathological examples // the statement does not have to be a compound statement switch (0) std::cout << "this does nothing\n"; // labels do not require a compound statement either 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 は浮動小数点変数の宣言である可能性があります。 | 禁止された |
[編集] 関連項目
| switch のC ドキュメント
|
[編集] 外部リンク
| 1. | ダフのデバイスを使用したループアンローリング |
| 2. | ダフのデバイスは C/C++ でコルーチンを実装するために使用できます |