La biblioteca C++17 de solo encabezado proporciona reflexión estática para enumeraciones, funciona con cualquier tipo de enumeración sin ninguna macro o código repetitivo.
Si le gusta este proyecto, considere hacer una donación a uno de los fondos que ayudan a las víctimas de la guerra en Ucrania: https://u24.gov.ua.
Básico
# include < magic_enum/magic_enum.hpp >
# include < iostream >
enum class Color : { RED = - 10 , BLUE = 0 , GREEN = 10 };
int main () {
Color c1 = Color::RED;
std::cout << magic_enum::enum_name (c1) << std::endl; // RED
return 0 ;
}
Valor de enumeración a cadena
Color color = Color::RED;
auto color_name = magic_enum::enum_name(color);
// color_name -> "RED"
Cadena al valor de enumeración
std::string color_name{ " GREEN " };
auto color = magic_enum::enum_cast<Color>(color_name);
if (color.has_value()) {
// color.value() -> Color::GREEN
}
// case insensitive enum_cast
auto color = magic_enum::enum_cast<Color>(value, magic_enum::case_insensitive);
// enum_cast with BinaryPredicate
auto color = magic_enum::enum_cast<Color>(value, []( char lhs, char rhs) { return std::tolower (lhs) == std::tolower (rhs); }
// enum_cast with default
auto color_or_default = magic_enum::enum_cast<Color>(value).value_or(Color::NONE);
Valor entero a enumeración
int color_integer = 2 ;
auto color = magic_enum::enum_cast<Color>(color_integer);
if (color.has_value()) {
// color.value() -> Color::BLUE
}
auto color_or_default = magic_enum::enum_cast<Color>(value).value_or(Color::NONE);
Acceso indexado al valor de enumeración
std:: size_t i = 0 ;
Color color = magic_enum::enum_value<Color>(i);
// color -> Color::RED
Secuencia de valores de enumeración
constexpr auto colors = magic_enum::enum_values<Color>();
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
// colors[0] -> Color::RED
Número de elementos de enumeración
constexpr std:: size_t color_count = magic_enum::enum_count<Color>();
// color_count -> 3
Valor de enumeración a entero
Color color = Color::RED;
auto color_integer = magic_enum::enum_integer(color); // or magic_enum::enum_underlying(color);
// color_integer -> 1
Secuencia de nombres de enumeración
constexpr auto color_names = magic_enum::enum_names<Color>();
// color_names -> {"RED", "BLUE", "GREEN"}
// color_names[0] -> "RED"
Secuencia de entradas de enumeración
constexpr auto color_entries = magic_enum::enum_entries<Color>();
// color_entries -> {{Color::RED, "RED"}, {Color::BLUE, "BLUE"}, {Color::GREEN, "GREEN"}}
// color_entries[0].first -> Color::RED
// color_entries[0].second -> "RED"
Fusión de enumeración para declaraciones de cambio/caso de varios niveles
switch (magic_enum::enum_fuse(color, direction).value()) {
case magic_enum::enum_fuse (Color::RED, Directions::Up). value (): // ...
case magic_enum::enum_fuse (Color::BLUE, Directions::Down). value (): // ...
// ...
}
Valor de tiempo de ejecución del interruptor de enumeración como constante constexpr
Color color = Color::RED;
magic_enum::enum_switch ([] ( auto val) {
constexpr Color c_color = val;
// ...
}, color);
Enum itera para cada enumeración como constante constexpr
magic_enum::enum_for_each<Color>([] ( auto val) {
constexpr Color c_color = val;
// ...
});
Compruebe si la enumeración contiene
magic_enum::enum_contains (Color::GREEN); // -> true
magic_enum::enum_contains<Color>( 2 ); // -> true
magic_enum::enum_contains<Color>( 123 ); // -> false
magic_enum::enum_contains<Color>( " GREEN " ); // -> true
magic_enum::enum_contains<Color>( " fda " ); // -> false
Índice de enumeración en secuencia
constexpr auto color_index = magic_enum::enum_index(Color::BLUE);
// color_index.value() -> 1
// color_index.has_value() -> true
Funciones para banderas
enum Directions : std:: uint64_t {
Left = 1 ,
Down = 2 ,
Up = 4 ,
Right = 8 ,
};
template <>
struct magic_enum ::customize::enum_range<Directions> {
static constexpr bool is_flags = true ;
};
magic_enum::enum_flags_name (Directions::Up | Directions::Right); // -> "Directions::Up|Directions::Right"
magic_enum::enum_flags_contains (Directions::Up | Directions::Right); // -> true
magic_enum::enum_flags_cast ( 3 ); // -> "Directions::Left|Directions::Down"
Nombre del tipo de enumeración
Color color = Color::RED;
auto type_name = magic_enum::enum_type_name<decltype(color)>();
// type_name -> "Color"
Operador IOstream para enumeración
using magic_enum::iostream_operators:: operator <<; // out-of-the-box ostream operators for enums.
Color color = Color::BLUE;
std::cout << color << std::endl; // "BLUE"
using magic_enum::iostream_operators:: operator >>; // out-of-the-box istream operators for enums.
Color color;
std::cin >> color;
Operador bit a bit para enumeración
enum class Flags { A = 1 << 0 , B = 1 << 1 , C = 1 << 2 , D = 1 << 3 };
using namespace magic_enum ::bitwise_operators ; // out-of-the-box bitwise operators for enums.
// Support operators: ~, |, &, ^, |=, &=, ^=.
Flags flags = Flags::A | Flags::B & ~Flags::C;
Comprueba si el tipo es una enumeración sin ámbito.
enum color { red, green, blue };
enum class direction { left, right };
magic_enum::is_unscoped_enum<color>::value -> true
magic_enum::is_unscoped_enum<direction>::value -> false
magic_enum::is_unscoped_enum< int >::value -> false
// Helper variable template.
magic_enum::is_unscoped_enum_v<color> -> true
Comprueba si el tipo es una enumeración con ámbito.
enum color { red, green, blue };
enum class direction { left, right };
magic_enum::is_scoped_enum<color>::value -> false
magic_enum::is_scoped_enum<direction>::value -> true
magic_enum::is_scoped_enum< int >::value -> false
// Helper variable template.
magic_enum::is_scoped_enum_v<direction> -> true
Variable de enumeración de almacenamiento estático a cadena. Esta versión es mucho más ligera en los tiempos de compilación y no está restringida a la limitación enum_range.
constexpr Color color = Color::BLUE;
constexpr auto color_name = magic_enum::enum_name<color>();
// color_name -> "BLUE"
containers::array
para enumeraciones.
magic_enum::containers::array<Color, RGB> color_rgb_array {};
color_rgb_array[Color::RED] = { 255 , 0 , 0 };
color_rgb_array[Color::GREEN] = { 0 , 255 , 0 };
color_rgb_array[Color::BLUE] = { 0 , 0 , 255 };
magic_enum::containers::get<Color::BLUE>(color_rgb_array) // -> RGB{0, 0, 255}
containers::bitset
para enumeraciones.
constexpr magic_enum::containers::bitset<Color> color_bitset_red_green {Color::RED|Color::GREEN};
bool all = color_bitset_red_green.all();
// all -> false
// Color::BLUE is missing
bool test = color_bitset_red_green.test(Color::RED);
// test -> true
containers::set
establecer contenedor para enumeraciones.
auto color_set = magic_enum::containers::set<Color>();
bool empty = color_set.empty();
// empty -> true
color_set.insert(Color::GREEN);
color_set.insert(Color::BLUE);
color_set.insert(Color::RED);
std:: size_t size = color_set.size();
// size -> 3
Tipo_subyacente mejorado "compatible con SFINAE" sin UB.
magic_enum::underlying_type<color>::type -> int
// Helper types.
magic_enum:: underlying_type_t <Direction> -> int
magic_enum
no pretende ser una solución milagrosa para la reflexión de enumeraciones, fue diseñado originalmente para enumeraciones pequeñas.
Antes de usar, lea las limitaciones de funcionalidad.
Debe agregar el archivo requerido magic_enum.hpp y, opcionalmente, otros encabezados del directorio de inclusión o del archivo de lanzamiento. Alternativamente, puede crear la biblioteca con CMake.
Si está utilizando vcpkg en su proyecto para dependencias externas, puede utilizar el paquete magic-enum.
Si está utilizando Conan para administrar sus dependencias, simplemente agregue magic_enum/xyz
a los requisitos de Conan, donde xyz
es la versión de lanzamiento que desea usar.
Si está utilizando Build2 para crear y administrar sus dependencias, agregue depends: magic_enum ^xyz
al archivo de manifiesto donde xyz
es la versión de lanzamiento que desea usar. Luego puedes importar el objetivo usando magic_enum%lib{magic_enum}
.
Alternativamente, puede usar algo como CPM que se basa en el módulo Fetch_Content
de CMake.
CPMAddPackage(
NAME magic_enum
GITHUB_REPOSITORY Neargye/magic_enum
GIT_TAG x.y.z # Where `x.y.z` is the release version you want to use.
)
Bazel también es compatible, simplemente agréguelo a su archivo WORKSPACE:
http_archive(
name = "magic_enum",
strip_prefix = "magic_enum-<commit>",
urls = ["https://github.com/Neargye/magic_enum/archive/<commit>.zip"],
)
Para usar bazel dentro del repositorio es posible hacer:
bazel build //...
bazel test //...
bazel run //example
(Tenga en cuenta que debe utilizar un compilador compatible o especificarlo con export CC= <compiler>
).
Si está utilizando Ros, puede incluir este paquete agregando <depend>magic_enum</depend>
a su paquete.xml e incluya este paquete en su espacio de trabajo. En su CMakeLists.txt agregue lo siguiente:
find_package (magic_enum CONFIG REQUIRED)
...
target_link_libraries (your_executable magic_enum::magic_enum)