Skip to content
Static reflection for enums (to string, from string, iteration) for modern C++, work with any enum type without any macro or boilerplate code
Branch: master
Clone or download
abelfodil and Neargye CMake enhancements
* Add magic_enum as an interface library
* Enable tests and examples only if is top project
* Use more modern approach to include directories
* Add install target
Latest commit e10ba18 Apr 22, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
example
include v0.4.2 Apr 10, 2019
test CMake enhancements Apr 21, 2019
.appveyor.yml v0.1.0 Mar 30, 2019
.gitignore dev v0.3.0 Apr 7, 2019
.travis.yml
CMakeLists.txt
LICENSE
README.md update readme Apr 10, 2019
install.cmake

README.md

Magic Enum C++

 __  __             _        ______                          _____
|  \/  |           (_)      |  ____|                        / ____|_     _
| \  / | __ _  __ _ _  ___  | |__   _ __  _   _ _ __ ___   | |   _| |_ _| |_
| |\/| |/ _` |/ _` | |/ __| |  __| | '_ \| | | | '_ ` _ \  | |  |_   _|_   _|
| |  | | (_| | (_| | | (__  | |____| | | | |_| | | | | | | | |____|_|   |_|
|_|  |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_|  \_____|
               __/ |
              |___/

Github Releases License Build Status Build status Codacy Badge Try online

What is Magic Enum?

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

  • enum_cast obtains enum value from string or integer.
  • enum_value returns enum value at specified index.
  • enum_values obtains enum value sequence.
  • enum_count returns number of enum values.
  • enum_name obtains string name from enum value.
  • enum_names obtains string enum name sequence.
  • is_unscoped_enum checks whether type is an Unscoped enumeration.
  • is_scoped_enum checks whether type is an Scoped enumeration.

Features

  • C++17
  • Header-only
  • Dependency-free
  • Compile-time
  • Enum to string
  • String to enum
  • Iterating over enum

Examples

// For example color enum.
enum Color { RED = 2, BLUE = 4, GREEN = 8 };
  • Enum value to string

    Color color = Color::RED;
    auto color_name = magic_enum::enum_name(color);
    if (color_name.has_value()) {
      // color_name.value() -> "RED"
    }
  • Static storage enum variable to string

    constexpr Color color = Color::BLUE;
    constexpr auto color_name = magic_enum::enum_name(color);
    if (color_name.has_value()) {
      // color_name.value() -> "BLUE"
    }
  • 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
    }
  • Static storage string to enum value

    constexpr auto color = magic_enum::enum_cast<Color>("BLUE");
    if (color.has_value()) {
      // color.value() -> Color::BLUE
    }
  • Integer to enum value

    int color_value = 2;
    auto color = magic_enum::enum_cast<Color>(color_value);
    if (colo.has_value()) {
      // color.value() -> Color::RED
    }
  • Static storage integer to enum value

    constexpr auto color = magic_enum::enum_cast<Color>(4);
    if (color.has_value()) {
      // color.value() -> Color::BLUE
    }
  • Indexed access to enum value

    int i = 1;
    Color colo = magic_enum::enum_value<Color>(i);
    // color -> Color::BLUE
  • Compile-time indexed access.

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

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

    constexpr std::size_t color_count = magic_enum::enum_count<Color>();
    // color_count -> 3
  • Enum names sequence

    constexpr auto color_names = magic_enum::enum_names<Color>();
    // color_names -> {"RED", "BLUE", "GREEN"}
  • Stream operator for enum

    using namespace magic_enum::ops; // out-of-the-box stream operator for enums.
    Color color = Color::BLUE;
    std::cout << color << std::endl; // "BLUE"
  • Checks whether type is an Unscoped enumeration.

    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
  • Checks whether type is an Scoped enumeration.

    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

Remarks

  • magic_enum::enum_cast returns std::optional<E>, using has_value() to check contains enum value and value() to get the enum value.

  • magic_enum::enum_value no bounds checking is performed: the behavior is undefined if index >= number of enum values.

  • magic_enum::enum_values returns std::array<E, N> with all enum value where N = number of enum values, sorted by enum value.

  • magic_enum::enum_name returns std::optional<std::string_view>, using has_value() to check contains enum name and value() to get the enum name.

  • magic_enum::enum_names returns std::array<std::string_view, N> with all string enum name where N = number of enum values, sorted by enum value.

  • Enum value must be in range [MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]. By default MAGIC_ENUM_RANGE_MIN = -128, MAGIC_ENUM_RANGE_MAX = 128.

    If need another range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN and MAGIC_ENUM_RANGE_MAX.

    #define MAGIC_ENUM_RANGE_MIN 0
    #define MAGIC_ENUM_RANGE_MAX 256
    #include <magic_enum.hpp>

    If need another range for specific enum type, add specialization enum_range for necessary enum type.

    #include <magic_enum.hpp>
    
    enum number { one = 100, two = 200, three = 300 };
    
    namespace magic_enum {
    template <>
    struct enum_range<number> {
      static constexpr int min = 100;
      static constexpr int max = 300;
    };
    }
  • magic_enum::enum_cast and magic_enum::enum_name obtains the first defined value enums, and won't work if value are aliased.

    enum ShapeKind {
      ConvexBegin = 0,
      Box = 0, // Won't work.
      Sphere = 1,
      ConvexEnd = 2,
      Donut = 2, // Won't work too.
      Banana = 3,
      COUNT = 4,
    };
    // magic_enum::enum_cast<ShapeKind>("Box") -> std::nullopt
    // magic_enum::enum_name(ShapeKind::Box) -> "ConvexBegin"

    Work around the issue:

    enum ShapeKind {
      // Convex shapes, see ConvexBegin and ConvexEnd below.
      Box = 0,
      Sphere = 1,
    
      // Non-convex shapes.
      Donut = 2,
      Banana = 3,
    
      COUNT = Banana + 1,
    
      // Non-reflected aliases.
      ConvexBegin = Box,
      ConvexEnd = Sphere + 1,
    };
    // magic_enum::enum_cast<ShapeKind>("Box") -> ShapeKind::Box
    // magic_enum::enum_name(ShapeKind::Box) -> "Box"
    
    // Non-reflected aliases.
    // magic_enum::enum_cast<ShapeKind>("ConvexBegin") -> std::nullopt
    // magic_enum::enum_name(ShapeKind::ConvexBegin) -> "Box"

Integration

You should add the required file magic_enum.hpp.

Compiler compatibility

  • Clang/LLVM >= 5
  • Visual C++ >= 15.3 / Visual Studio >= 2017
  • Xcode >= 10.2
  • GCC >= 9

Licensed under the MIT License

You can’t perform that action at this time.