枚举类可以转换为基础类型吗?

时间:2013-01-29 18:10:47

标签: c++ c++11

有没有办法将enum class字段转换为基础类型?我认为这是自动的,但显然不是。

enum class my_fields : unsigned { field = 1 };

unsigned a = my_fields::field;

该任务被海湾合作委员会拒绝。 error: cannot convert 'my_fields' to 'unsigned int' in assignment

4 个答案:

答案 0 :(得分:165)

我认为您可以使用std::underlying_type来了解基础类型,然后使用cast:

#include <type_traits> //for std::underlying_type

typedef std::underlying_type<my_fields>::type utype;

utype a = static_cast<utype>(my_fields::field);

有了这个,您不必假设基础类型,或者您不必在enum class的定义中提及enum class my_fields : int { .... }或如此。

您甚至可以编写通用转换函数,该函数应该能够将任何 enum class转换为其基础整数类型:

template<typename E>
constexpr auto to_integral(E e) -> typename std::underlying_type<E>::type 
{
   return static_cast<typename std::underlying_type<E>::type>(e);
}

然后使用它:

auto value = to_integral(my_fields::field);

auto redValue = to_integral(Color::Red);//where Color is an enum class!

由于函数声明为constexpr,因此您可以在需要常量表达式的地方使用它:

int a[to_integral(my_fields::field)]; //declaring an array

std::array<int, to_integral(my_fields::field)> b; //better!

希望有所帮助。

答案 1 :(得分:38)

您无法隐式转换 ,但可以进行显式转换:

enum class my_fields : unsigned { field = 1 };

// ...

unsigned x = my_fields::field; // ERROR!
unsigned x = static_cast<unsigned>(my_fields::field); // OK

还要注意这样一个事实,即分号应该是在你的枚举定义中的之后,而不是之前。

答案 2 :(得分:0)

在必须正确序列化枚举值时,我发现以下函数deploy.rb很有用。

underlying_cast

答案 3 :(得分:0)

正如其他人指出的那样,没有隐式强制转换,但是您可以使用显式static_cast。我在代码中使用以下辅助函数来与枚举类型及其基础类进行相互转换。

    template<typename EnumType>
    constexpr inline decltype(auto) getIntegralEnumValue(EnumType enumValue)
    {
        static_assert(std::is_enum<EnumType>::value,"Enum type required");
        using EnumValueType = std::underlying_type_t<EnumType>;
        return static_cast<EnumValueType>(enumValue);
    }

    template<typename EnumType,typename IntegralType>
    constexpr inline EnumType toEnum(IntegralType value)
    {
        static_assert(std::is_enum<EnumType>::value,"Enum type required");
        static_assert(std::is_integral<IntegralType>::value, "Integer required");
        return static_cast<EnumType>(value);
    }

    template<typename EnumType,typename UnaryFunction>
    constexpr inline void setIntegralEnumValue(EnumType& enumValue, UnaryFunction integralWritingFunction)
    {
        // Since using reinterpret_cast on reference to underlying enum type is UB must declare underlying type value and write to it and then cast it to enum type
        // See discussion on https://stackoverflow.com/questions/19476818/is-it-safe-to-reinterpret-cast-an-enum-class-variable-to-a-reference-of-the-unde

        static_assert(std::is_enum<EnumType>::value,"Enum type required");

        auto enumIntegralValue = getIntegralEnumValue(enumValue);
        integralWritingFunction(enumIntegralValue);
        enumValue = toEnum<EnumType>(enumIntegralValue);
    }

使用代码

enum class MyEnum {
   first = 1,
   second
};

MyEnum myEnum = MyEnum::first;
std::cout << getIntegralEnumValue(myEnum); // prints 1

MyEnum convertedEnum = toEnum(1);

setIntegralEnumValue(convertedEnum,[](auto& integralValue) { ++integralValue; });
std::cout << getIntegralEnumValue(convertedEnum); // prints 2