2009-07-28 13 views
2

数値データ型で使用するためのテンプレート変換関数が用意されています。その中には、ポインタのような型でコンパイルされないようにする構造体が含まれています。C++のenumの乗算はどのように機能しますか?

template<class To, class From> 
To ConvertTo(From what) 
{ 
    assert(2 * what == what * 2); // this will not compile for pointers 
    //skipped 
} 

この関数は、コンパイルされ、列挙型は、2番目のテンプレートパラメータとして渡されたときにオールライト動作します:VC++ 7に意図したとおりに

enum TSomeEnum { 
    SE_First, 
    SE_Second  
}; 

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

上記のコードはコンパイルして実行します。

操作*はどのように列挙型で機能しますか?それは未定義の振る舞いの方法ですか?

答えて

5

Enumsがintsに劣化している(古いCの機能)ので、これがなぜ機能しているのですか。私はそれが未定義の行動だとは思わないが、あなたが望まない/期待していないような行動かもしれない。

+6

列挙型のすべての値を格納できる基本的な整数型に列挙する列挙型です。 Degrate to 'int'はC++では正しくありません。 –

0

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

コンパイラおそらく

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

として、あなたの上記列挙型を格納し、私はこの番号付けシステムは、C/C++標準の一部である場合やコンパイラはそれを行うだけかどうかはわかりませんが、私は常にましたそれらを順番に見た。

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

+0

私のコメントを参照してください他の2つの投稿に "整数"。値を返すと、最初の列挙子(明示的な初期化なし)が値0を持つことが標準で保証されます。後続の各列挙子は、明示的な値を指定しない限り、以前の列挙子+1の値を持ちます。 –

2

数値は、算術演算のために整数に昇格されます。

列挙型の値は、常にゼロから番号付けされます(これは標準の一部です)が、あなたが好きな値を指定することができます。自動ナンバリングは、明示的に番号が付けられた最後のアイテムから段階的に実行されます。 コンパイラは、列挙型を格納するすべての値を含む最小の整数型を使用します。

例えば:それが動作する理由

enum foo 
{ 
    VALUE0, /* = 0 */ 
    VALUE1, /* = 1 */ 
    VALUE3 = 1234, 
    VALUE4 /* = 1235 */ 
}; 
+0

列挙型には、基本的な表現があります。これは 'signed char'の場合がありますが、intにプロモートされますが、基になる型もunsigned intであり、宣伝は行われません。 –

2

を使用することができ、私はpeterchenは理想的な答えを持っていると思うが、ブーストはあなたのために多すぎると、にあなたの現在のバージョンを変更します。

template<class To, class From> 
To ConvertTo(From what, From checkConvertableToInt = 2) 
{ 
} 

C++ doesnの」整数から列挙への暗黙的な変換を可能にします。同様に、NULLポインタ定数(0)を暗黙的にポインタ型に変換することのみが可能です。

その他の回答の中には、intとして実装されている列挙型やint型に昇格されている列挙型を参照するものがあります。本当じゃない。 C++では、エニュメレーションにすべての値を格納できる基になる型を持つ列挙型が定義されています。

enum E { 
    E0 
    , E1=MAX_INT+1u 
}; 

あなたが運転中にそれを使用する場合、列挙は、その基になる型のための規則に従います。以下の列挙は、したがって、「unsigned int型」の基になる型以上の符号付き/符号なし整数型を持つことになります。

+1

+1は、enumをテストするために代入を使用しますが、副作用のあるアサーションには注意してください。 – iain

+1

@Iain:これをキャッチしてくれてありがとう、私の変更は元のプログラムの動作を完全に変更しました。私は今、デフォルトの引数の一部として代入を持つようにサンプルを更新しました。アサートをまったく使用する必要はありません。 –

+0

@リチャード素敵! – iain

1

リチャード・コーデンの答えは、アサーション内でコードが強制的に実行されることを確かめることができないため、アサーションで列挙型を強制的に強制的に機能させる良いメカニズムです。

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

template<class To, class From> 
To ConvertTo(From what) 
{ 
    assert(testIntegralType(what)); 
} 

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