C++ 枚举类可以转换为底层类型吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14589417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:29:11  来源:igfitidea点击:

Can an enum class be converted to the underlying type?

c++c++11

提问by edA-qa mort-ora-y

Is there a way to convert an enum classfield to the underlying type? I thought this would be automatic, but apparently not.

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

enum class my_fields : unsigned { field = 1 };

unsigned a = my_fields::field;

That assignment is being rejected by GCC. error: cannot convert 'my_fields' to 'unsigned int' in assignment.

该任务被 GCC 拒绝。error: cannot convert 'my_fields' to 'unsigned int' in assignment.

回答by Nawaz

I think you can use std::underlying_typeto know the underlying type, and then use cast:

我认为您可以使用std::underlying_type来了解底层类型,然后使用强制转换:

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

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

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

With this, you don't have to assumethe underlying type, or you don't have to mention it in the definition of the enum classlike enum class my_fields : int { .... }or so.

有了这个,您就不必假设底层类型,或者不必在enum class诸如此类的定义中提及它enum class my_fields : int { .... }

You can even write a genericconvert function that should be able to convert anyenum classto its underlying integraltype:

您甚至可以编写一个通用的convert 函数,它应该能够将any转换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);
}

then use it:

然后使用它:

auto value = to_integral(my_fields::field);

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

And since the function is declared to be constexpr, you can use it where constant expression is required:

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

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

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

回答by Andy Prowl

You cannot convert it implicitly, but an explicit cast is possible:

您不能隐式转换它,但可以进行显式转换:

enum class my_fields : unsigned { field = 1 };

// ...

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

Also mind the fact, that the semicolon should be afterthe closed curly brace in your enum's definition, not before.

还要注意一个事实,分号应该在枚举定义中的闭合花括号之后,而不是之前。

回答by James

I find the following function underlying_castuseful when having to serialise enum values correctly.

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

namespace util
{

namespace detail
{
    template <typename E>
    using UnderlyingType = typename std::underlying_type<E>::type;

    template <typename E>
    using EnumTypesOnly = typename std::enable_if<std::is_enum<E>::value, E>::type;

}   // namespace util.detail


template <typename E, typename = detail::EnumTypesOnly<E>>
constexpr detail::UnderlyingType<E> underlying_cast(E e) {
    return static_cast<detail::UnderlyingType<E>>(e);
}

}   // namespace util

enum SomeEnum : uint16_t { A, B };

void write(SomeEnum /*e*/) {
    std::cout << "SomeEnum!\n";
}

void write(uint16_t /*v*/) {
    std::cout << "uint16_t!\n";
}

int main(int argc, char* argv[]) {
    SomeEnum e = B;
    write(util::underlying_cast(e));
    return 0;
}