27

C++11 では、厳密に型指定された列挙型 ( enum class) をその基になる型にキャストできます。しかし、ポインタを同じものにキャストできないようです:

enum class MyEnum : int {};

int main()
{
  MyEnum me;

  int iv = static_cast<int>(me); // works
  int* ip = static_cast<int*>(&me); // "invalid static_cast"
}

なぜこれが必要なのかを理解しようとしています.enumメカニズムについて、これをサポートするのが困難または無意味になるものはありますか? 規格上の単純な見落としですか?他の何か?

列挙型が上記のように整数型の上に真に構築されている場合、値だけでなくポインターもキャストできるはずです。または C スタイルのキャストを引き続き使用できますreinterpret_cast<int*>が、それは必要だと思っていたよりも大きなハンマーです。

4

6 に答える 6

8

代わりに、少し異なる方法でそれを見てください。基になる表現が同一であってもstatic_cast、することはできません。同じ理由で、に基づく列挙型はまだ一意で無関係な型として扱われているため、.long*int*intlongintintreinterpret_cast

于 2014-07-04T04:33:03.593 に答える
3

あなたの質問に対する答えは、標準草案のセクション5.2.9 静的キャストにあります。

許可のサポート

int iv = static_cast<int>(me);

以下から入手できます。

5.2.9/9 スコープ列挙型 (7.2) の値は、整数型に明示的に変換できます。元の値が指定された型で表現できる場合、値は変更されません。それ以外の場合、結果の値は指定されていません。

許可のサポート

me = static_cast<MyEnum>(100);

以下から入手できます。

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

許可しないためのサポート

int* ip = static_cast<int*>(&me);

以下から入手できます。

5.2.9/11 タイプ「cv1 B へのポインター」の prvalue (B はクラス タイプ) は、タイプ「cv2 D へのポインター」の prvalue に変換できます。ここで、D は B から派生したクラス (条項 10) です。 、「D へのポインター」から「B へのポインター」への有効な標準変換が存在する場合 (4.10)、cv2 は cv1 と同じ cv 修飾であるか、cv1 よりも大きい cv 修飾であり、B は仮想基本クラスではありません。 D は、D の仮想基底クラスの基底クラスでもありません。null ポインター値 (4.10) は、変換先の型の null ポインター値に変換されます。型「cv1 B へのポインター」の prvalue が、実際には型 D のオブジェクトのサブオブジェクトである B を指している場合、結果のポインターは型 D の外側のオブジェクトを指します。それ以外の場合、キャストの結果は未定義です。

static_castsinceへ&meのキャストには使用できず、継承によって関連付けられていません。int*MyEnumint

于 2014-07-08T18:57:07.273 に答える
1

最初の理由は、古いスタイルを期待したり、列挙に定義された値の束を使用したり、整数型を直接期待したりstatic_castする関数やライブラリを操作できることだと思います。ただし、型と整数型のenum間には他の論理的な関係はないため、そのキャストが必要な場合は使用する必要があります。ただし、問題がある場合は、独自のヘルパーを使用できます。enumreinterpret_castreinterpret_cast

template< class EnumT >
typename std::enable_if<
    std::is_enum<EnumT>::value,
    typename std::underlying_type<EnumT>::type*
>::type enum_as_pointer(EnumT& e)
{
    return reinterpret_cast<typename std::underlying_type<EnumT>::type*>(&e);
}

また

template< class IntT, class EnumT >
IntT* static_enum_cast(EnumT* e, 
    typename std::enable_if<
        std::is_enum<EnumT>::value &&
        std::is_convertible<
            typename std::underlying_type<EnumT>::type*,
            IntT*
        >::value
    >::type** = nullptr)
{
    return reinterpret_cast<typename std::underlying_type<EnumT>::type*>(&e);
}

この回答は について満足できないかもしれませんが、それらreason of prohibiting static_cast of enum pointersを安全に使用する方法を提供reinterpret_castします。

于 2014-07-08T13:20:02.760 に答える