Reputation: 454
I have a variable declared as:
enum class FooEnum: uint64_t {}
and I would like to cast to its base-type, but I don't want to hardcode the base-type. For instance, something like this:
FooEnum myEnum;
uint64_t * intPointer = (underlying_typeof(myEnum))&myEnum;
Is this possible?
Upvotes: 38
Views: 14288
Reputation: 361442
Since C++ 11 you can use this:
std::underlying_type
class template to know the underlying type of enum.The doc says,
Defines a member
typedef
type of type that is the underlying type for the enumeration T.
So you should be able to do this:
#include <type_traits> //include this
FooEnum myEnum;
auto pointer = static_cast<std::underlying_type<FooEnum>::type*>(&myEnum);
In C++ 14 it has been a bit simplified (note there is no ::type
):
auto pointer = static_cast<std::underlying_type_t<FooEnum>*>(&myEnum);
And finally since C++ 23 one can get value without explicit cast (docs):
auto value = std::to_underlying<FooEnum>(myEnum);
Upvotes: 46
Reputation: 145279
Both Visual C++ 10.0 and MinGW g++ 4.6.1 lack std::underlying_type
, but both accept this code:
template< class TpEnum >
struct UnderlyingType
{
typedef typename conditional<
TpEnum( -1 ) < TpEnum( 0 ),
typename make_signed< TpEnum >::type,
typename make_unsigned< TpEnum >::type
>::type T;
};
Upvotes: 9
Reputation: 626
Here is another approach for when underlying_type is not present. This method doesn't attempt to detect the signed-ness of the enum, just give you a type of the same size, which is more than enough for a lot of situations.
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;
};
Usage:
enum EFoo {Alpha, Beta};
EFoo f = Alpha;
TIntegerForEnum<EFoo>::type i = f;
TIntegerForEnum<decltype(f)>::type j = f;
Upvotes: 2
Reputation: 218770
Your guessed syntax is amazingly close. You're looking for std::underlying_type
in <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;
}
Upvotes: 20