2012-02-18 71 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 2012-02-18 17:26:34

+5

@ L7ColWinters' dynamic_cast'不能幫助。不要讓'class'關鍵字和':uint64_t'誤導你認爲範圍枚舉和枚舉類型與類繼承類似。 – 2012-02-18 21:39:38

回答

33

您可以使用此:

doc說,

定義成員typedef類型是爲枚舉T.

所以,你應該能夠做到這一點的基礎類型:

#include <type_traits> //include this 

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

我刪除了我的答案,然後upvoted你的。但是我寫這個時,你還沒有編譯你的答案。所以我改變了主意,取消了我的回答。 ;-) – 2012-02-18 17:43:23

+0

'static_cast'會起作用嗎?我的印象是,沒有一個理智的演員會在'enum class'上工作。 – 2012-02-21 18:50:23

16

Your 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 2012-02-18 22:08:06

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),則值不變,否則結果值未指定(並且可能不在該範圍內)。 – 2014-02-28 07:56:17

+1

@Joker_vD:未指定不是UB。 – 2014-11-28 03:38:34

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;