enum X : int
(C#)と、またはenum class X : int
(C ++ 11)の隠れた内部フィールド有するタイプであるint
ことは、任意の値を保持することができます。さらに、いくつかの定義済み定数がX
列挙型で定義されています。列挙型を整数値にキャストしたり、その逆を行うことができます。これは、C#とC ++ 11の両方に当てはまります。
C#では、列挙型は個々の値を保持するためだけでなく、Microsoftの推奨に従って、フラグのビットごとの組み合わせを保持するためにも使用されます。このような列挙型は(通常、必ずしもそうではありませんが)[Flags]
属性で装飾されています。開発者の生活を楽にするために、ビット単位の演算子(OR、ANDなど)がオーバーロードされているため、次のようなことが簡単にできます(C#)。
void M(NumericType flags);
M(NumericType.Sign | NumericType.ZeroPadding);
私は経験豊富なC#開発者ですが、C ++をプログラミングしてから数日しか経っていないため、C ++の規約については知りません。C#で使用したのとまったく同じ方法でC ++ 11列挙型を使用する予定です。C ++ 11では、スコープ付き列挙型のビット演算子はオーバーロードされないため、それらをオーバーロードしたかったのです。
これは議論を呼び起こし、意見は3つの選択肢の間で異なるようです:
C#と同様に、ビット型を保持するために列挙型の変数が使用されます。
void M(NumericType flags); // With operator overloading: M(NumericType::Sign | NumericType::ZeroPadding); // Without operator overloading: M(static_cast<NumericType>(static_cast<int>(NumericType::Sign) | static_cast<int>(NumericType::ZeroPadding)));
しかし、これはC ++ 11のスコープ付き列挙型の厳密に型指定された列挙型の哲学に反するでしょう。
列挙型のビットごとの組み合わせを保存する場合は、プレーン整数を使用します。
void M(int flags); M(static_cast<int>(NumericType::Sign) | static_cast<int>(NumericType::ZeroPadding));
しかし、これはすべてをに減らし
int
、メソッドにどのタイプを入れるべきかについての手がかりを与えません。演算子をオーバーロードし、非表示の整数フィールドにビット単位のフラグを保持する別のクラスを作成します。
class NumericTypeFlags { unsigned flags_; public: NumericTypeFlags () : flags_(0) {} NumericTypeFlags (NumericType t) : flags_(static_cast<unsigned>(t)) {} //...define BITWISE test/set operations }; void M(NumericTypeFlags flags); M(NumericType::Sign | NumericType::ZeroPadding);
(user315052による完全なコード)
しかし、その場合、可能な値を示唆するIntelliSenseなどのサポートはありません。
これは主観的な質問であることは知っていますが、どのアプローチを使用すればよいですか?C ++で最も広く認識されているのは、もしあれば、どのようなアプローチですか?ビットフィールドを扱うとき、どのようなアプローチを使用しますか?
もちろん、3つのアプローチすべてが機能するため、単に個人的な好みではなく、事実上および技術上の理由、一般に受け入れられている慣習を探しています。
たとえば、C#のバックグラウンドのため、C ++のアプローチ1を使用する傾向があります。これには、私の開発環境が可能な値を教えてくれるという追加の利点があり、オーバーロードされた列挙演算子を使用すると、これは簡単に記述して理解でき、非常にきれいです。また、メソッドのシグネチャは、期待される値の種類を明確に示しています。しかし、ここにいるほとんどの人は、おそらく正当な理由で、私に反対しています。
enum E { A = 1, B = 2, C = 4, };
、範囲は0..7
(3ビット)このように、C ++標準は、明示的に#1は常に実行可能な選択肢となることを保証【具体的には、。enum class
デフォルトenum class : int
特に指定し、したがって常に一定下地タイプを持っていない限り。])