2012-02-18 14 views
28

私のように宣言された変数があります。クラスの列挙型の基本的な型を知るには?

enum class FooEnum: uint64_t {} 

を、私はそのベース型にキャストしたいと思いますが、私は基本型をハードコーディングする必要はありません。たとえば、次のようなものがあります。

FooEnum myEnum; 
uint64_t * intPointer = (underlying_typeof(myEnum))&myEnum; 

これは可能ですか?

+0

http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast鋳造、L7ColWinters @特にダイナミック – L7ColWinters

+5

' dynamic_cast'は助けません。 'class'キーワードと':uint64_t'が、スコープ付きの列挙型と根底にあるタイプの列挙型がクラス継承に似ていると誤解させてはいけません。 –

答えて

33

あなたはこれを使用することができます:

  • std::underlying_typeクラステンプレートを列挙の基になる型を知っています。

doc

だから、あなたがこれを行うことができるはず列挙T.

ための基本となるタイプですタイプのメンバーtypedefタイプを定義し、こう述べています。

#include <type_traits> //include this 

FooEnum myEnum; 
auto pointer = static_cast<std::underlying_type<FooEnum>::type*>(&myEnum); 
+2

私は自分の答えを削除し、あなたのものをupvoted。しかし、私はこれを書いているようにあなたの答えを集めていません。だから私は心を変え、私の答えを元に戻した。 ;-) –

+0

'static_cast'は動作しますか?私は、 'enum class 'でうまくいったキャストはできないという印象を受けました。 –

16

g残念なことに構文は驚くほど近いです。あなたは<type_traits>std::underlying_type探している:

#include <type_traits> 
#include <cstdint> 

enum class FooEnum: std::uint64_t {}; 

int main() 
{ 
    FooEnum myEnum; 
    uint64_t* intPointer = (std::underlying_type<FooEnum>::type*)&myEnum; 
} 
+0

本当に近いです。明らかに適切な名前が選ばれました。 : – Kyle

7

両方のVisual C++ 10.0とMinGWのgの++ 4.6.1 std::underlying_typeが不足しているが、両方は、このコードを受け入れる:

template< class TpEnum > 
struct UnderlyingType 
{ 
    typedef typename conditional< 
     TpEnum(-1) < TpEnum(0), 
     typename make_signed<TpEnum>::type, 
     typename make_unsigned<TpEnum>::type 
     >::type T; 
}; 
+0

@ Cheersandhth.-Alf @Grizzly:しかしながら、キャスト 'TpEnum(-1)'と 'TpEnum(0)' *はUBを持つかもしれません:5.2.9 "静的キャスト"、項目10は "積分値または列挙型を列挙型に明示的に変換することができます。元の値が列挙値の範囲(7.2)の範囲内であれば値は変更されませんが、それ以外の場合は結果の値が指定されません。 –

+1

@Joker_vD:未指定はUBではありません。 –

2

ここでは、のために別のアプローチでありますunderlying_typeは存在しません。このメソッドは、列挙型の署名付き文字を検出しようとせず、同じサイズの型を与えます。これは、多くの状況で十分です。

template<int> 
class TIntegerForSize 
{ 
    typedef void type; 
}; 

template<> 
struct TIntegerForSize<1> 
{ 
    typedef uint8_t type; 
}; 

template<> 
struct TIntegerForSize<2> 
{ 
    typedef uint16_t type; 
}; 

template<> 
struct TIntegerForSize<4> 
{ 
    typedef uint32_t type; 
}; 

template<> 
struct TIntegerForSize<8> 
{ 
    typedef uint64_t type; 
}; 

template<typename T> 
struct TIntegerForEnum 
{ 
    typedef typename TIntegerForSize<sizeof(T)>::type type; 
}; 

使用法:

enum EFoo {Alpha, Beta}; 
EFoo f = Alpha; 
TIntegerForEnum<EFoo>::type i = f; 
TIntegerForEnum<decltype(f)>::type j = f;