36

まず、cppreference.com によると、列挙型を値で初期化することはやや不可能です。

http://en.cppreference.com/w/cpp/language/value_initializationによると、列挙型を値で初期化すると、実際にはゼロ初期化が実行されます。次に、http://en.cppreference.com/w/cpp/language/zero_initializationによると、列挙型をゼロ初期化する効果は次のとおりです。

がスカラー型の場合T、オブジェクトの初期値は、暗黙的に に変換された整数定数ゼロTです。

ただし、整数定数ゼロは暗黙的に列挙型に変換できません。最終的に、列挙型を値で初期化することはできません。これは奇妙に聞こえますが、enum の値の初期化は VC、GCC、および clang で機能します。それで、標準はこれについて何と言っていますか?

次に、http ://en.cppreference.com/w/cpp/language/static_cast によると:

整数、浮動小数点、または列挙型は、任意の完全な列挙型に変換できます (結果は未定義です (C++17 まで) 未定義の動作 (C++17 以降) 式の値が列挙型の基になる型に変換される場合) 、対象の列挙値の 1 つではありません)

それで、これは、列挙型を値で初期化すると(それが機能する場合)、ターゲット列挙型に等しい列挙子がない場合、実際には未定義の動作につながる可能性があることを意味します0か?

4

2 に答える 2

4

これに対する答えはコメントで与えられました。その背後にある標準全体を説明する私の試みを以下に示します。

型のオブジェクトまたは参照をゼロで初期化Tするとは、次のことを意味します。

  • がスカラー型 (3.9) の場合、オブジェクトは整数リテラル(ゼロ) を にT変換して得られる値に初期化されます。0T

(列挙型はスカラー型です; §3.9/9) したがって、変換は暗黙的であるとは言われていないので、§4 ではなく §5.2.9 を見ています。

式の結果は、式を typestatic_cast<T>(v)に変換した結果です。vT

§5.2.9/10 では、整数値を列挙型に変換する方法を定義しています。

整数型または列挙型の値は、明示的に列挙型に変換できます。元の値が列挙値 (7.2) の範囲内にある場合、値は変更されません。それ以外の場合、結果の値は指定されていません (その範囲にない可能性があります)。

すべての列挙の列挙値の範囲内にゼロがあることを示す必要があります。
次の 5 つの引用は、§7.2/8 からの抜粋です。

基になる型が固定されている列挙の場合、列挙の値は基になる型の値になります。

許可されているすべての基になる型の値の範囲にゼロが含まれている*ため、これにより自動的に目的の結果が得られます。ここで、基になる型が固定されていない列挙の場合、

それ以外の場合、e minが最小の列挙子でe maxが最大の列挙の場合、列挙の値は、次のように定義されたb minからb maxの範囲の値になります。

つまり、b minは常にゼロ以下であり、b maxは常にゼロ以上であることを示す必要があります。

Kを 2 の補数表現の場合は 1 とし、1 の補数表現または符号-大きさ表現の場合は 0 とします。
b maxmax(|e min | − K, |e max |)以上で2M − 1に等しい最小値で、 Mは負でない整数です。

|最大| は負ではなく、2 つの数値の最大値は少なくとも両方の数値と同じ大きさです。したがって、 max(|e min | − K, |e max |)も非負であり、b maxはその数値以上でなければならないため、最初の要件が満たされます。

e minが負でない場合はb minはゼロであり、そうでない場合は-(b max + K)です。

b minは明らかにゼロまたは負です。b maxは上記のように非負であり、Kは非負 (0 または 1) であるため、それらの合計の加法逆数は正ではありません。2 番目の要件が満たされました。ついに、

enumerator-listが空の場合、列挙の値は、列挙が value を持つ単一の列挙子を持っているかのようになります0

これにより、e min = e max = 0を設定することで上記の結果が得られます。


  • これは、「すべての整数型の値の範囲はゼロである」という主張に還元されます。これは、読者に証明するために残されています。
于 2015-05-10T16:30:51.553 に答える