Как узнать базовый тип перечисления класса?

У меня есть переменная, объявленная как:

enum class FooEnum: uint64_t {}

и я хотел бы использовать его базовый тип, но я не хочу жестко задавать базовый тип. Например, что-то вроде этого:

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

Возможно ли это?

Ответ 1

Вы можете использовать это:

  • std::underlying_type шаблон класса, чтобы узнать базовый тип перечисления.

doc говорит,

Определяет тип элемента typedef типа, который является базовым типом для перечисления T.

Итак, вы должны это сделать:

#include <type_traits> //include this

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

Ответ 2

Ваш угаданный синтаксис поразительно близок. Вы ищете std::underlying_type в <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;
}

Ответ 3

Оба Visual С++ 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;
};

Ответ 4

Вот еще один подход, когда base_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;