MIT License

项目介绍

Neargye/magic_enum 是一个托管在 GitHub 上的开源项目,主要使用 C++ 编写,采用 MIT License 许可证,目前获得 6.3k 个 Star、560 次 Fork。

仓库全名
Neargye/magic_enum
开源许可证
MIT License
Star 数
6.3k
Fork 数
560
未关闭 Issue
1

README 摘要

Magic Enum C++ A header-only C++17 library for enum reflection, without registration macros or boilerplate. Documentation Reference Limitations Integration Features & Examples Basic String to enum value Integer to enum value Indexed access to enum value Enum value sequence Number of enum values Enum value to integer Enum name sequence Enum entry sequence Enum fusion for multi-level switch/case statements On MSVC,…

完整内容见 GitHub 原始 README 或本页 。

常见问题

magic_enum 用什么语言开发?

主要使用 C++ 编写,采用 MIT License 许可证,目前有 6.3k 个 Star。

magic_enum 可以免费商用吗?

仓库采用 MIT License 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 magic_enum 的源码?

可以直接克隆仓库:git clone https://github.com/Neargye/magic_enum.git,默认分支为 master;安装与运行步骤见仓库 README。

magic_enum 最近还在维护吗?

仓库最近一次更新为 1 天前,当前有 1 个未关闭 Issue;Star 数为 6.3k,可作为社区活跃度的参考。

README

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

Magic Enum C++

A header-only C++17 library for enum reflection, without registration macros or boilerplate.

Documentation

Features & Examples

  • 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;
    }
    
  • 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)); });
    
  • 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(): // ...
        break;
      case magic_enum::enum_fuse(Color::BLUE, Directions::Down).value(): // ...
        break;
    // ...
    }
    

    On MSVC, this switch triggers warning C4064. See enum_fuse.

  • 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 can be reflected

    magic_enum::enum_reflected(Color::GREEN); // -> true
    magic_enum::enum_reflected<Color>(1);     // -> true, but not an enumerator
    
  • 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,
    };
    MAGIC_ENUM_DEFINE_BITWISE_OPERATORS(Directions); // From <magic_enum/magic_enum_bitwise.hpp>.
    
    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
    

    Note: bitwise operators found through ADL automatically enable flag reflection. Only named zero and single bits are reflected. For combinations, enum_flags_name joins their bit names. To keep ordinary reflection, set customize::enum_range<E>::is_flags = false or define MAGIC_ENUM_NO_AUTO_IS_FLAGS for the whole build.

  • 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

    #include <magic_enum/magic_enum_iostream.hpp>
    
    enum class Color { RED, GREEN, BLUE };
    MAGIC_ENUM_DEFINE_IOSTREAM_OPERATORS(Color); // Operators for Color only, no using needed.
    
    Color color = Color::BLUE;
    std::cout << color << std::endl; // "BLUE"
    std::cin >> color;
    
  • Bitwise operators for enums

    #include <magic_enum/magic_enum_bitwise.hpp>
    
    enum class Flags { A = 1 << 0, B = 1 << 1, C = 1 << 2, D = 1 << 3 };
    MAGIC_ENUM_DEFINE_BITWISE_OPERATORS(Flags); // Defines ~, |, &, ^, |=, &=, ^= for Flags.
    
    Flags flags = Flags::A | (Flags::B & ~Flags::C);
    

    For a nested enum, use MAGIC_ENUM_DEFINE_FRIEND_* inside its class. Prefer these macros to operator namespaces, which affect every enum in scope. See operator namespace risks.

  • Formatting

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

    For {fmt}, include it before magic_enum_format.hpp.

  • Scoped and unscoped enum traits

    enum color { red, green, blue };
    enum class direction { left, right };
    
    static_assert(magic_enum::is_unscoped_enum_v<color>);
    static_assert(magic_enum::is_scoped_enum_v<direction>);
    
  • Compile-time enum value to string, without the enum_range limit.

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

    // In enum_values order: RED, BLUE, GREEN.
    constexpr auto color_rgb_values = magic_enum::containers::make_array<Color>(RGB{255, 0, 0}, RGB{0, 0, 255}, RGB{0, 255, 0});
    
    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

    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

    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

    static_assert(std::is_same_v<magic_enum::underlying_type_t<Color>, int>);
    

Integration

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

  • With CMake 3.22+, use 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. The 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. On MSVC, Visual Studio 2026 or newer 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"
    

    Use either the headers or the module in the whole program. Build and use an installed module with the same compiler, standard library and C++ standard. pkg-config provides only the header-only target.

    Optional settings:

    • MAGIC_ENUM_MODULE_WITH_FMT=ON enables {fmt} through fmt::fmt. The {fmt} module is not supported.
    • MAGIC_ENUM_MODULE_IMPORT_STD=ON enables import std. It requires CMAKE_CXX_STANDARD 23 or later, CMake 3.31+ and a toolchain with import std support.

Compiler compatibility

  • Clang/LLVM >= 9
  • MSVC >= 19.20 / Visual Studio >= 2019 (16.0)
  • Xcode >= 11
  • GCC >= 9

C++26 reflection is selected automatically when available. See limitations.

Licensed under the MIT License

评论

暂无评论