2012-02-18 18 views
28

mam zmienna zadeklarowana jako:Jak poznać podstawowy rodzaj wyliczenia w klasie?

enum class FooEnum: uint64_t {} 

i chciałbym oddać do jego podstawowej typu, ale nie chcę aby hardcode bazowy typu. Na przykład coś takiego:

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

Czy to możliwe?

+0

http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast casting, specjalnie dynamiczny – L7ColWinters

+5

@ L7ColWinters ' dynamic_cast' nie może pomóc. Nie pozwól, aby słowo kluczowe "class" i ': uint64_t' wprowadzały użytkownika w błąd, że zakresy wyliczeń i typy wyrażeń są podobne do dziedziczenia klas. –

Odpowiedz

33

Można to wykorzystać:

doc mówi

określa element typedef typ typu że to podstawowy typ dla T. wyliczania

więc powinieneś być w stanie to zrobić:

#include <type_traits> //include this 

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

Usunąłem moją odpowiedź, a następnie przegłosowałem twoje. Ale nie kompilujesz odpowiedzi, pisząc to. Więc zmieniłem zdanie i cofnąłem odpowiedź. ;-) –

+0

Czy "static_cast" działa? Miałem wrażenie, że żadna zdrowa obsada nie zadziała na "klasie enum". –

16

Twój użyta składnia jest niesamowicie bliska. Szukasz std::underlying_type w <type_traits>:

#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

Tak blisko. Najwyraźniej wybrano odpowiednią nazwę. :) – Kyle

7

Zarówno Visual C++ 10,0 i MinGW g ++ 4.6.1 brakuje std::underlying_type, ale zarówno zaakceptować ten kod:

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: Jednak rzuca 'TpEnum (-1)' i 'TpEnum (0)' * może * mieć UB: 5.2.9 "Statyczna obsada", pozycja 10 mówi "Wartość całki lub typ wyliczeniowy można jawnie przekonwertować do typu wyliczenia.Na wartość jest niezmieniona, jeśli pierwotna wartość jest w zakresie wartości wyliczenia (7.2) .W przeciwnym razie wynikowa wartość jest nieokreślona (i może nie być w tym zakresie). " –

+1

@Joker_vD: nieokreślony nie jest UB. –

2

Oto inne podejście do kiedy basis_type nie jest obecny. Ta metoda nie próbuje wykryć podpisu enum, wystarczy podać typ tego samego rozmiaru, który jest więcej niż wystarczający dla wielu sytuacji.

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; 
}; 

Zastosowanie:

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