33499

[code]

    enum class Color
    {
        RED,
        GREEN,
        BLUE,
        totalNum
    };
    
    void func(int in)
    {
        Color color = static_cast<Color>(in);
        switch(color)
        {
            case Color::RED:
            break;
            ...
        }
    }
    
[/code]

上記のようなコードなんですが、enumの範囲外(0~3以外)が入力されるかもしれない場合にどうするのが一般的なのでしょうか？  
そのままstatic_castしてswitchのdefaultで処理すればいいでしょうか。

ガードを入れるとか？

[code]

    //ガード
    if(in < 0 || in >= totalNum) return;
    
[/code]

でもこれだとenumが連続でない場合に複雑になるよな、と悩んでいます。

よろしくお願いします。


CC BY-SA 3.0
2017-03-23T11:49:46.437
33490
2017-03-23T23:56:41.763
18547
question
c++
enum範囲外のint値をstatic_castする際の処理


C++ 言語規格書 JIS X 3014:2003 によると  
5.2.9 静的キャスト の 7 項

>
> 汎整数型又は列挙型の値は、明示的に列挙型に変換することができる。元の値が変換先の列挙型の値の範囲内にある場合、その結果の値は元の値のままとする。そうでない場合、結果の列挙型の値は、未規定とする。

7.2 列挙体宣言の 9

> 列挙型の列挙値の範囲にある場合、値は、変換によっても変化しない。そうでない場合、結果の列挙値は、規定しない。

この質問は最後の状況なので未規定、つまり  
\- プログラムとしては正しい（暴走したりすることはない）  
\- 処理系実装者は「どう挙動するか」について文書を記さなくて良い

言語規格書的回答としては「仮引数の型を `int` → `enum`
にすべき」でしょう。そうすれば未規定の状況を避けることができてより厳密で安全になります。

実装上はどうか、を考えるに  
\- C/C++ は性能を追求する言語であること（無駄なことは一切しない）  
\- 列挙型は整数 (特に `int` ) で実装されていること  
から、処理系がどう挙動するかはほぼ自明です。要するに整数値をそのまま扱うだけです。整数型の値がそのまま列挙型の内部表現として扱われるだけ、つまり列挙型の定義にない値になる、と考えてよいです。定義に無い値をどれかの１つの値に変換するような無駄な処理はしないと期待してよいと思います。  
（手元の処理系複数個で皆同じ挙動をすることをアセンブラレベルで確認済み）  
なので

> そのままstatic_castしてswitchのdefaultで処理すればいいでしょうか。

実用上は、これで良いと思います。

でもこのような要件で最もふさわしいのは `enum class` だと思う。


CC BY-SA 3.0
2017-03-23T23:56:41.763
33499
2017-03-23T23:56:41.763
8589
33490
answer