c++ - que - ¿Se puede convertir una clase enum al tipo subyacente?
que es un enum en java (3)
Creo que puedes usar std::underlying_type para conocer el tipo subyacente, y luego usar cast:
#include <type_traits> //for std::underlying_type
typedef std::underlying_type<my_fields>::type utype;
utype a = static_cast<utype>(my_fields::field);
Con esto, no tienes que asumir el tipo subyacente, o no tienes que mencionarlo en la definición de la enum class
enum class my_fields : int { .... }
como enum class my_fields : int { .... }
o menos.
Incluso puede escribir una función de conversión genérica que debería poder convertir cualquier enum class
a su tipo integral subyacente:
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);
}
luego úsalo:
auto value = to_integral(my_fields::field);
auto redValue = to_integral(Color::Red);//where Color is an enum class!
Y como la función se declara como constexpr
, puede usarla cuando se requiera expresión constante:
int a[to_integral(my_fields::field)]; //declaring an array
std::array<int, to_integral(my_fields::field)> b; //better!
Espero que ayude.
¿Hay alguna manera de convertir un campo de enum class
al tipo subyacente? Pensé que esto sería automático, pero aparentemente no.
enum class my_fields : unsigned { field = 1 };
unsigned a = my_fields::field;
Esa asignación está siendo rechazada por GCC. error: cannot convert ''my_fields'' to ''unsigned int'' in assignment
.
Encuentro útil la siguiente función underlying_cast
al tener que serializar valores enum correctamente.
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;
}
No puede convertirlo implícitamente , pero es posible un lanzamiento explícito:
enum class my_fields : unsigned { field = 1 };
// ...
unsigned x = my_fields::field; // ERROR!
unsigned x = static_cast<unsigned>(my_fields::field); // OK
También tenga en cuenta el hecho de que el punto y coma debería ser después del corchete cerrado en la definición de su enum, no antes.