Is it possible to convert an enumeration class to a base type?

Is there a way to convert an enum class field to a base type? I thought it would be automatic, but apparently not.

 enum class my_fields : unsigned { field = 1 }; unsigned a = my_fields::field; 

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

+83
c ++ c ++ 11
Jan 29 '13 at 18:10
source share
3 answers

I think you can use std :: basic_type to find out the base type and then use cast:

 #include <type_traits> //for std::underlying_type typedef std::underlying_type<my_fields>::type utype; utype a = static_cast<utype>(my_fields::field); 

However, you do not need to assume the base type, or you do not need to mention it in the definition of enum class as enum class my_fields : int { .... } or so.

You can even write a generator conversion function that should be able to convert any enum class into its main integral type:

 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 as constexpr , you can use it where a constant expression is required:

 int a[to_integral(my_fields::field)]; //declaring an array std::array<int, to_integral(my_fields::field)> b; //better! 

Hope this helps.

+145
Jan 29 '13 at 18:16
source share

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 note that the semicolon should be after the closed curly bracket in the definition of the enumeration, and not earlier.

+36
Jan 29 '13 at 18:16
source share

I find the following underlying_cast function useful when serializing enum values ​​correctly.

 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; } 
0
Jul 27 '17 at 15:06
source share



All Articles