2


0

数値データ型で使用するためのテンプレート変換関数があります。 その中にはポインタのような型でコンパイルしないようにする構文が含まれています。

テンプレートTo ConvertTo(From what){assert(2 * what == what * 2); //これはポインタ用にコンパイルされません//スキップされます}

この関数は、2番目のテンプレートパラメータとしてenumが渡されたときにコンパイルして問題なく動作します。

列挙型TSomeEnum {SE_First、SE_Second};

TSomeEnum enumValue = SE_First; int result = ConvertTo(enumValue);

上記のコードは、VC 7で意図したとおりにコンパイルおよび実行されます。

操作*は列挙型に対してどのように機能しますか? 未定義の動作への道ですか。

6 Answer


5


列挙型はint(古いCの機能)に格下げされるので、これが機能する理由です。 私はそれが未定義の振る舞いだとは思わないが、それはあなたが望まない/期待しない振る舞いのようなものかもしれない。


2


列挙型は算術演算用に整数に変換されます。

enumの値は常にゼロから数えられます(これは標準の一部です)が、好きな値を指定できます。 その後、自動番号付けは、明示的に番号付けした最後の項目から徐々に増加します。 コンパイラは、enumのすべての値を含む最小の整数型を使用してそれを格納します。

例えば:

列挙型foo {VALUE0、/ * = 0 * / VALUE1、/ * = 1 * / VALUE3 = 1234、VALUE4 / * = 1235 * /}。


2


私は peterchenが理想的な答えを持っていると思いますが、あなたにとってブーストが大きすぎる場合は現在のバージョン

テンプレートからConvertTo(何から、From checkConvertableToInt = 2){}

Cは、整数から列挙型への暗黙の型変換を許可しません。 同様に、nullポインタ定数(0)をポインタ型に暗黙的に変換することしかできません。

他の回答の中には、列挙型がintとして実装されている、またはint型に昇格されていることを示しているものがあります。 本当じゃない。 Cでは、列挙型は、列挙型のすべての値を格納できる基本型を持つように定義されています。 したがって、次の列挙型は、基になるタイプの 'unsigned int’またはより大きい符号付き/符号なし整数型になります。

列挙型E {E0、E1 = MAX_INT 1u};

列挙型は、操作で使用するときに、その基になる型の規則に従います。


1


Timoはそれがなぜ機能するのか説明しました。

より安全なテストには、http://www.boost.org/doc/libs/1_39_0/libs/type_traits/doc/html/index.html [`boost

TypeTraits`]を使うことができます


1


Richard Cordenの答えは、列挙型をアサートで失敗させるための優れたメカニズムを提供しますが、アサーション内のコードが常に実行されるとは限らないため、副作用が問題を引き起こす可能性があります。

このテストはおそらく副作用を避けるために一般的な関数に置かれるべきです。

テンプレートからConvertTo(何から){assert(testIntegralType(何)); }

template void testIntegralType(T val){T v1 = val; assert(2 * v1 == 2 * val); }


0


列挙型は整数として格納され、さらに整数にキャストすることもできます。

コンパイラはおそらくあなたの上記のenumを以下のように格納しました。

enum TSomeEnum {SE_First = 0、SE_SEcond = 1};

この番号付けシステムがC / C規格の一部であるのか、コンパイラがそれをどのように行っているのかはわかりませんが、私はいつもそれらを順番に見てきました。

とにかく、あなたの質問に答えるために、彼らはその下にintとして格納されているので、それは乗算することができるはずです。 ただし、コンパイラによっては型変換についての警告を表示することがあります。