La bibliothèque C++17 en en-tête uniquement fournit une réflexion statique pour les énumérations, fonctionne avec n'importe quel type d'énumération sans aucune macro ou code passe-partout.
Si vous aimez ce projet, pensez à faire un don à l'un des fonds qui viennent en aide aux victimes de la guerre en Ukraine : https://u24.gov.ua.
Basique
# 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 ;
}
Valeur d'énumération dans la chaîne
Color color = Color::RED;
auto color_name = magic_enum::enum_name(color);
// color_name -> "RED"
Chaîne pour énumérer la valeur
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);
Entier pour énumérer la valeur
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);
Accès indexé à la valeur enum
std:: size_t i = 0 ;
Color color = magic_enum::enum_value<Color>(i);
// color -> Color::RED
Séquence de valeurs d'énumération
constexpr auto colors = magic_enum::enum_values<Color>();
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
// colors[0] -> Color::RED
Nombre d'éléments d'énumération
constexpr std:: size_t color_count = magic_enum::enum_count<Color>();
// color_count -> 3
Valeur d'énumération en entier
Color color = Color::RED;
auto color_integer = magic_enum::enum_integer(color); // or magic_enum::enum_underlying(color);
// color_integer -> 1
Séquence de noms d'énumération
constexpr auto color_names = magic_enum::enum_names<Color>();
// color_names -> {"RED", "BLUE", "GREEN"}
// color_names[0] -> "RED"
Séquence d'entrées d'énumération
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"
Fusion d'énumérations pour les instructions de commutation/cas à plusieurs niveaux
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 (): // ...
// ...
}
Enum valeur d'exécution du commutateur en tant que constante constexpr
Color color = Color::RED;
magic_enum::enum_switch ([] ( auto val) {
constexpr Color c_color = val;
// ...
}, color);
Itération d'énumération pour chaque énumération en tant que constante constexpr
magic_enum::enum_for_each<Color>([] ( auto val) {
constexpr Color c_color = val;
// ...
});
Vérifiez si l'énumération contient
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
Index d'énumération en séquence
constexpr auto color_index = magic_enum::enum_index(Color::BLUE);
// color_index.value() -> 1
// color_index.has_value() -> true
Fonctions pour les drapeaux
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"
Nom du type d'énumération
Color color = Color::RED;
auto type_name = magic_enum::enum_type_name<decltype(color)>();
// type_name -> "Color"
Opérateur IOstream pour l'énumération
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;
Opérateur au niveau du bit pour l'énumération
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;
Vérifie si le type est une énumération sans portée.
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
Vérifie si le type est une énumération étendue.
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 d'énumération de stockage statique en chaîne Cette version est beaucoup plus légère sur les temps de compilation et n'est pas limitée à la limitation enum_range.
constexpr Color color = Color::BLUE;
constexpr auto color_name = magic_enum::enum_name<color>();
// color_name -> "BLUE"
containers::array
array conteneur pour les énumérations.
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
conteneur de bitset pour les énumérations.
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
définit le conteneur pour les énumérations.
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
Type de sous-jacent "compatible SFINAE-friendly" sans UB amélioré.
magic_enum::underlying_type<color>::type -> int
// Helper types.
magic_enum:: underlying_type_t <Direction> -> int
magic_enum
ne prétend pas être une solution miracle pour la réflexion sur les énumérations, il a été conçu à l'origine pour les petites énumérations.
Avant utilisation, lisez les limitations de fonctionnalité.
Vous devez ajouter le fichier requis magic_enum.hpp et éventuellement d'autres en-têtes du répertoire d'inclusion ou de l'archive de publication. Alternativement, vous pouvez créer la bibliothèque avec CMake.
Si vous utilisez vcpkg sur votre projet pour des dépendances externes, vous pouvez utiliser le package magic-enum.
Si vous utilisez Conan pour gérer vos dépendances, ajoutez simplement magic_enum/xyz
aux exigences de votre conan, où xyz
est la version que vous souhaitez utiliser.
Si vous utilisez Build2 pour créer et gérer vos dépendances, ajoutez depends: magic_enum ^xyz
au fichier manifeste où xyz
est la version que vous souhaitez utiliser. Vous pouvez ensuite importer la cible en utilisant magic_enum%lib{magic_enum}
.
Alternativement, vous pouvez utiliser quelque chose comme CPM qui est basé sur le module 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 est également pris en charge, ajoutez simplement à votre fichier WORKSPACE :
http_archive(
name = "magic_enum",
strip_prefix = "magic_enum-<commit>",
urls = ["https://github.com/Neargye/magic_enum/archive/<commit>.zip"],
)
Pour utiliser Bazel dans le référentiel, il est possible de faire :
bazel build //...
bazel test //...
bazel run //example
(Notez que vous devez utiliser un compilateur pris en charge ou le spécifier avec export CC= <compiler>
.)
Si vous utilisez Ros, vous pouvez inclure ce package en ajoutant <depend>magic_enum</depend>
à votre package.xml et inclure ce package dans votre espace de travail. Dans votre CMakeLists.txt, ajoutez ce qui suit :
find_package (magic_enum CONFIG REQUIRED)
...
target_link_libraries (your_executable magic_enum::magic_enum)