2012-02-18 7 views
28

que tienen una variable declarada como:¿Cómo saber el tipo subyacente de la enumeración de la clase?

enum class FooEnum: uint64_t {} 

y me gustaría echar a su tipo de base, pero no quieren codificar el tipo de base. Por ejemplo, algo como esto:

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

¿Esto es posible?

+0

http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast fundición, específicamente dinámico – L7ColWinters

+5

@ L7ColWinters ' dynamic_cast' no puede ayudar. No permita que la palabra clave 'class' y': uint64_t' lo induzca a error al pensar que las enumeraciones de ámbito y los tipos subyacentes de enumeraciones son similares a la herencia de clases. –

Respuesta

33

Puede utilizar esta:

El doc dice,

Define un miembro typedef tipo de tipo que es el tipo subyacente de la T. enumeración

Por lo que debe ser capaz de hacer esto:

#include <type_traits> //include this 

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

Suprimí mi respuesta y luego volé tuya. Pero no estás compilando tu respuesta aún mientras escribo esto. Así que cambié de opinión y recuperé mi respuesta. ;-) –

+0

¿Funcionaría un 'static_cast'? Tenía la impresión de que ningún molde sano funcionaría en una 'clase enum'. –

16

Tu g La sintaxis sugerida es asombrosamente cercana. Usted está buscando std::underlying_type en <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

Tan cerca de hecho. Aparentemente se eligió un nombre apropiado. :) – Kyle

7

Tanto Visual C++ 10.0 y MinGW g ++ 4.6.1 carecen std::underlying_type, pero ambos aceptar este código:

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: Sin embargo, arroja 'TpEnum (-1)' y 'TpEnum (0)' * puede * tener UB: 5.2.9 "Estático elenco", el elemento 10 dice "Un valor de integral o el tipo de enumeración puede convertirse explícitamente a un tipo de enumeración. El valor no cambia si el valor original está dentro del rango de los valores de enumeración (7.2). De lo contrario, el valor resultante no está especificado (y podría no estar en ese rango). " –

+1

@Joker_vD: no especificado no es UB. –

2

Aquí es otro enfoque para cuando underlying_type no está presente. Este método no intenta detectar la firma de la enumeración, solo le da un tipo del mismo tamaño, que es más que suficiente para muchas situaciones.

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

Uso:

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