Skip to content

Repository files navigation

Github releases Conan package Vcpkg package Build2 package Meson wrap License Compiler explorer OpenSSF Scorecard

Magic Enum C++

Header-only C++17 library provides static reflection for enums, work with any enum type without any macro or boilerplate code.

Documentation

  • Basic

    #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;
    }
  • Enum value to string

    Color color = Color::RED;
    auto color_name = magic_enum::enum_name(color);
    // color_name -> "RED"
  • String to enum value

    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_case_insensitive = magic_enum::enum_cast<Color>(color_name, magic_enum::case_insensitive);
    
    // enum_cast with BinaryPredicate
    auto color_with_predicate = magic_enum::enum_cast<Color>(color_name, [](char lhs, char rhs) { return std::tolower(static_cast<unsigned char>(lhs)) == std::tolower(static_cast<unsigned char>(rhs)); });
    
    // enum_cast with default
    auto color_or_default = magic_enum::enum_cast<Color>(color_name).value_or(Color::RED);
  • Integer to enum value

    int color_integer = 0;
    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>(123).value_or(Color::RED);
  • Indexed access to enum value

    std::size_t i = 0;
    Color color = magic_enum::enum_value<Color>(i);
    // color -> Color::RED
  • Enum value sequence

    constexpr auto colors = magic_enum::enum_values<Color>();
    // colors -> {Color::RED, Color::BLUE, Color::GREEN}
    // colors[0] -> Color::RED
  • Number of enum values

    constexpr std::size_t color_count = magic_enum::enum_count<Color>();
    // color_count -> 3
  • Enum value to integer

    Color color = Color::RED;
    auto color_integer = magic_enum::enum_integer(color); // or magic_enum::enum_underlying(color);
    // color_integer -> -10
  • Enum name sequence

    constexpr auto color_names = magic_enum::enum_names<Color>();
    // color_names -> {"RED", "BLUE", "GREEN"}
    // color_names[0] -> "RED"
  • Enum entry sequence

    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"
  • Enum fusion for multi-level switch/case statements

    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(): // ...
    // ...
    }
  • Runtime enum value as constexpr constant

    Color color = Color::RED;
    magic_enum::enum_switch([](auto val) {
      constexpr Color c_color = val;
      // ...
    }, color);
  • Iterate over enum values as constexpr constants

    magic_enum::enum_for_each<Color>([](auto val) {
      constexpr Color c_color = val;
      // ...
    });
  • Move through enum values

    magic_enum::enum_next_value(Color::RED);          // -> optional containing Color::BLUE
    magic_enum::enum_prev_value_circular(Color::RED); // -> Color::GREEN
  • Check whether enum contains value

    magic_enum::enum_contains(Color::GREEN); // -> true
    magic_enum::enum_contains<Color>(0); // -> true
    magic_enum::enum_contains<Color>(123); // -> false
    magic_enum::enum_contains<Color>("GREEN"); // -> true
    magic_enum::enum_contains<Color>("fda"); // -> false
  • Check whether value is in reflection range

    magic_enum::enum_reflected<Color>(123); // -> true
    magic_enum::enum_contains<Color>(123);  // -> false
    magic_enum::enum_reflected<Color>(128); // -> false
  • Enum index in sequence

    constexpr auto color_index = magic_enum::enum_index(Color::BLUE);
    // color_index.value() -> 1
    // color_index.has_value() -> true
  • Flag operations

    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;
    };
    using namespace magic_enum::bitwise_operators; // Use with care; operators are enabled for all enums.
    
    magic_enum::enum_flags_name(Directions::Up | Directions::Right); // -> "Up|Right"
    magic_enum::enum_flags_name(Directions::Up | Directions::Right, ','); // -> "Up,Right"
    magic_enum::enum_flags_contains(Directions::Up | Directions::Right); // -> true
    magic_enum::enum_flags_cast<Directions>(3).value(); // -> Directions::Left|Directions::Down
    magic_enum::enum_flags_cast<Directions>("Left,Down", ',').value(); // -> Directions::Left|Directions::Down
    magic_enum::enum_flags_test(Directions::Up | Directions::Right, Directions::Up); // -> true
    magic_enum::enum_flags_test_any(Directions::Left | Directions::Down, Directions::Down | Directions::Right); // -> true
    magic_enum::is_flags_v<Directions>; // -> true
  • Enum type name

    Color color = Color::RED;
    auto type_name = magic_enum::enum_type_name<decltype(color)>();
    // type_name -> "Color"
  • I/O stream operators for enums

    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;
  • Bitwise operators for enums

    enum class Flags { A = 1 << 0, B = 1 << 1, C = 1 << 2, D = 1 << 3 };
    using namespace magic_enum::bitwise_operators; // Use with care; operators are enabled for all enums.
    // Support operators: ~, |, &, ^, |=, &=, ^=.
    Flags flags = Flags::A | (Flags::B & ~Flags::C);
  • Formatting

    #include <format>
    #include <magic_enum/magic_enum_format.hpp>
    
    std::format("{}", Color::RED); // -> "RED"
    std::format("{}", Color{42});  // -> "42"

    Include {fmt} before magic_enum_format.hpp to enable {fmt} formatter support.

  • Unscoped enum trait

    enum color { red, green, blue };
    enum class direction { left, right };
    
    magic_enum::is_unscoped_enum_v<color> -> true
    magic_enum::is_unscoped_enum_v<direction> -> false
  • Scoped enum trait

    enum color { red, green, blue };
    enum class direction { left, right };
    
    magic_enum::is_scoped_enum_v<color> -> false
    magic_enum::is_scoped_enum_v<direction> -> true
  • Compile-time enum value to string. This overload compiles faster and is not restricted by enum_range limitation.

    constexpr Color color = Color::BLUE;
    constexpr auto color_name = magic_enum::enum_name<color>();
    // color_name -> "BLUE"
  • containers::array array container for enums.

    constexpr auto color_rgb_values = magic_enum::containers::make_array<Color>(RGB{255, 0, 0}, RGB{0, 255, 0}, RGB{0, 0, 255});
    
    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 bitset container for enums.

    constexpr magic_enum::containers::bitset<Color> color_bitset {Color::RED, Color::GREEN};
    color_bitset.test(Color::RED);  // -> true
    color_bitset.test(Color::BLUE); // -> false
    
    std::uint8_t incoming = 0b00000011;
    auto raw_bitset = magic_enum::containers::bitset<Color> {magic_enum::containers::raw_access, incoming};
  • containers::set set container for enums.

    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
    
    using color_name_set = magic_enum::containers::set<Color, magic_enum::containers::name_less<>>;
    color_name_set colors_by_name {Color::RED, Color::GREEN, Color::BLUE};
  • Underlying type

    magic_enum::underlying_type<Color>::type -> int
    magic_enum::underlying_type_t<Color> -> int

Integration

  • Copy required headers from include/magic_enum or use release archive. magic_enum_all.hpp includes all public headers.

  • Use CMake with add_subdirectory or find_package(magic_enum CONFIG REQUIRED), then link magic_enum::magic_enum.

  • Use vcpkg, Conan, Build2, or Meson.

  • Fetch sources with CMake FetchContent or CPM.cmake. Release tags use vx.y.z format.

  • Use Bazel with MODULE.bazel or http_archive; target is @magic_enum//:magic_enum.

  • Use ROS with <depend>magic_enum</depend> in package.xml, then link magic_enum::magic_enum.

  • CMake targets:

    • magic_enum::magic_enum is the header-only target.
    • magic_enum::magic_enum_module is the C++20 module target. Enable it with MAGIC_ENUM_USE_MODULES=ON. CMake 3.28+ is required.

    Build the module target:

    cmake -S . -B build -G Ninja -DMAGIC_ENUM_USE_MODULES=ON
    cmake --build build

    Link the module target:

    find_package(magic_enum CONFIG REQUIRED)
    target_link_libraries(your_executable PRIVATE magic_enum::magic_enum_module)
    set_target_properties(your_executable PROPERTIES CXX_EXTENSIONS OFF CXX_SCAN_FOR_MODULES ON)

    Import the module:

    import magic_enum;
    
    enum class Color { RED, GREEN, BLUE };
    auto name = magic_enum::enum_name(Color::RED); // "RED"

    Do not use #include <magic_enum/...> and import magic_enum; in the same program. Use the same compiler, standard library, and C++ standard when building and consuming an installed module. The pkg-config package supports only the header-only target.

    Optional settings:

    • Set MAGIC_ENUM_MODULE_WITH_FMT=ON to enable {fmt} support through fmt::fmt. It is disabled by default. The {fmt} C++ module is not supported.
    • Set MAGIC_ENUM_MODULE_IMPORT_STD=ON to enable import std support. This requires a compatible CMake toolchain.

Header-only compiler compatibility

  • Clang/LLVM >= 5
  • MSVC++ >= 15.3 / Visual Studio >= 2017
  • Xcode >= 10
  • GCC >= 9

Licensed under the MIT License

About

Static reflection for enums (to string, from string, iteration) for modern C++, work with any enum type without any macro or boilerplate code

Topics

Resources

Security policy

Stars

6.2k stars

Watchers

65 watching

Forks

Releases

Packages

Used by

Contributors

Languages