A biblioteca C++ 17 somente de cabeçalho fornece reflexão estática para enums, funciona com qualquer tipo de enum sem qualquer macro ou código padrão.
Se você gosta deste projeto, considere fazer uma doação para um dos fundos que ajudam as vítimas da guerra na Ucrânia: 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 enum para string
Color color = Color::RED;
auto color_name = magic_enum::enum_name(color);
// color_name -> "RED"
String para valor enum
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 inteiro para enum
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);
Acesso indexado ao valor enum
std:: size_t i = 0 ;
Color color = magic_enum::enum_value<Color>(i);
// color -> Color::RED
Sequência de valores enum
constexpr auto colors = magic_enum::enum_values<Color>();
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
// colors[0] -> Color::RED
Número de elementos enum
constexpr std:: size_t color_count = magic_enum::enum_count<Color>();
// color_count -> 3
Valor enum para número inteiro
Color color = Color::RED;
auto color_integer = magic_enum::enum_integer(color); // or magic_enum::enum_underlying(color);
// color_integer -> 1
Sequência de nomes de enum
constexpr auto color_names = magic_enum::enum_names<Color>();
// color_names -> {"RED", "BLUE", "GREEN"}
// color_names[0] -> "RED"
Sequência de entradas enum
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"
Fusão de enum para instruções switch/case de vários níveis
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 tempo de execução do switch Enum como constante constexpr
Color color = Color::RED;
magic_enum::enum_switch ([] ( auto val) {
constexpr Color c_color = val;
// ...
}, color);
Enum iterado para cada enum como constante constexpr
magic_enum::enum_for_each<Color>([] ( auto val) {
constexpr Color c_color = val;
// ...
});
Verifique se enum contém
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 Enum em sequência
constexpr auto color_index = magic_enum::enum_index(Color::BLUE);
// color_index.value() -> 1
// color_index.has_value() -> true
Funções para sinalizadores
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"
Nome do tipo de enumeração
Color color = Color::RED;
auto type_name = magic_enum::enum_type_name<decltype(color)>();
// type_name -> "Color"
Operador IOstream para enum
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 enum
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;
Verifica se o tipo é uma enumeração sem escopo.
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
Verifica se o tipo é uma enumeração com escopo.
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
Variável enum de armazenamento estático para string Esta versão é muito mais leve nos tempos de compilação e não está restrita à limitação enum_range.
constexpr Color color = Color::BLUE;
constexpr auto color_name = magic_enum::enum_name<color>();
// color_name -> "BLUE"
containers::array
para enums.
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
contêiner de bits para enumerações.
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
define contêiner para enumerações.
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 subjacente "compatível com SFINAE" sem UB aprimorado.
magic_enum::underlying_type<color>::type -> int
// Helper types.
magic_enum:: underlying_type_t <Direction> -> int
magic_enum
não pretende ser uma solução mágica para reflexão de enums, ele foi originalmente projetado para enums pequenos.
Antes de usar, leia as limitações de funcionalidade.
Você deve adicionar o arquivo necessário magic_enum.hpp e, opcionalmente, outros cabeçalhos de include dir ou release archive. Alternativamente, você pode construir a biblioteca com CMake.
Se você estiver usando vcpkg em seu projeto para dependências externas, poderá usar o pacote magic-enum.
Se você estiver usando o Conan para gerenciar suas dependências, basta adicionar magic_enum/xyz
aos requisitos do seu conan, onde xyz
é a versão de lançamento que você deseja usar.
Se você estiver usando Build2 para construir e gerenciar suas dependências, adicione depends: magic_enum ^xyz
ao arquivo de manifesto onde xyz
é a versão de lançamento que você deseja usar. Você pode então importar o alvo usando magic_enum%lib{magic_enum}
.
Alternativamente, você pode usar algo como CPM que é baseado no módulo Fetch_Content
do 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 também é compatível, basta adicionar ao seu arquivo WORKSPACE:
http_archive(
name = "magic_enum",
strip_prefix = "magic_enum-<commit>",
urls = ["https://github.com/Neargye/magic_enum/archive/<commit>.zip"],
)
Para usar o bazel dentro do repositório é possível fazer:
bazel build //...
bazel test //...
bazel run //example
(Observe que você deve usar um compilador compatível ou especificá-lo com export CC= <compiler>
.)
Se estiver usando Ros, você pode incluir este pacote adicionando <depend>magic_enum</depend>
ao seu package.xml e incluir este pacote em seu espaço de trabalho. No seu CMakeLists.txt adicione o seguinte:
find_package (magic_enum CONFIG REQUIRED)
...
target_link_libraries (your_executable magic_enum::magic_enum)