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

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

Github releases Conan package Vcpkg package License Build status Build status Codacy badge Try online Compiler explorer

Magic Enum C++

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_integer obtains integer value from enum value.
  • enum_name returns name from enum value.
  • enum_names obtains string enum name sequence.
  • enum_entries obtains pair (value enum, string enum name) sequence.
  • enum_index obtains index in enum value sequence from enum value.
  • enum_contains checks whether enum contains enumerator with such value.
  • enum_type_name returns name of enum type.
  • is_unscoped_enum checks whether type is an Unscoped enumeration.
  • is_scoped_enum checks whether type is an Scoped enumeration.
  • underlying_type improved UB-free "SFINAE-friendly" underlying_type.
  • ostream_operators ostream operators for enums.
  • bitwise_operators bitwise operators for enums.

Documentation

Features

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

Examples

// For example color enum.
enum class Color { RED = 2, BLUE = 4, GREEN = 8 };
  • 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
    }
  • Integer to enum value

    int color_integer = 2;
    auto color = magic_enum::enum_cast<Color>(color_integer);
    if (color.has_value()) {
      // color.value() -> Color::RED
    }
  • Indexed access to enum value

    std::size_t i = 1;
    Color color = magic_enum::enum_value<Color>(i);
    // color -> Color::BLUE
  • 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 elements

    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);
    // color -> 2
  • Enum names sequence

    constexpr auto& color_names = magic_enum::enum_names<Color>();
    // color_names -> {"RED", "BLUE", "GREEN"}
    // color_names[0] -> "RED"
  • Enum entries 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"
  • Ostream operator for enum

    using namespace magic_enum::ostream_operators; // out-of-the-box ostream operators for enums.
    Color color = Color::BLUE;
    std::cout << color << std::endl; // "BLUE"
  • Bitwise operator for 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;
  • 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
  • Static storage enum variable to string This version is much lighter on the compile times and is not restricted to the enum_range limitation.

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

Remarks

  • magic_enum does not pretend to be a silver bullet for reflection for enums, it was originally designed for small enum.

  • Before use, read the limitations of functionality.

  • For the small enum use the API from the namespace magic_enum, and for enum-flags use the API from the namespace magic_enum::flags.

Integration

  • You should add the required file magic_enum.hpp.

  • If you are using vcpkg on your project for external dependencies, then you can use the magic-enum package.

  • If you are using Conan to manage your dependencies, merely add magic_enum/x.y.z to your conan's requires, where x.y.z is the release version you want to use.

  • Alternatively, you can use something like CPM which is based on CMake's Fetch_Content module.

    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 is also supported, simply add to your WORKSPACE file:

    http_archive(
        name = "magic_enum",
        strip_prefix = "magic_enum-<commit>",
        urls = ["https://github.com/Neargye/magic_enum/archive/<commit>.zip"],
    )
    

    To use bazel inside the repository it's possible to do:

    bazel build //...
    bazel test //...
    bazel run //:example
    

    (Note that you must use a supported compiler or specify it with export CC= <compiler>.)

Compiler compatibility

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

Licensed under the MIT License

Comments
  • Breakage in Clang trunk

    Breakage in Clang trunk

    Clang has recently addressed an https://github.com/llvm/llvm-project/issues/50055 where it failed to diagnose the UB of casting an out-of-range integer to an enum in a constant expression.

    Since undefined behavior is not allowed in a constant expression, Clang now prohibits enum test { zero }; constexpr int g = static_cast<test>(-1); with error: constexpr variable 'g' must be initialized by a constant expression; note: integer value -1 is outside the valid range of values [0, 1] for this enumeration type

    This change breaks magic_enum library, since the library internally uses the [-128, 128] default enum value range. Demonstrated with example, below

    #include "magic_enum.hpp"                                
                                                                                    
    enum Color { Red, Black };                                                      
    int main(int argc, char* argv[]) {
       Color color = Red;                                                                                                   
       magic_enum::enum_name(color);                                                                                                            
       return 0;                                                                     
    }                                                                                                                      
    
    invalid 
    opened by hokein 19
  • Support converting enum value from non-constexpr to constexpr context

    Support converting enum value from non-constexpr to constexpr context

    Hi,

    Is there any way magic_enum could support converting a non constexpr enum value into a constexpr context for all values of a given enum. It's currently possible to do this manually (or automatically if you have access to the enum source and can change the definition to use X Macros) but it would be great if it could be supported natively by the lib.

    Motivating example using X Macros: https://godbolt.org/z/rr4n15cEG

    enhancement help wanted 
    opened by andrewkcorcoran 19
  • Compiler croaks if max/min interval is too wide

    Compiler croaks if max/min interval is too wide

    I am encountering problems if the max/min interval is too wide. The interval limit appears to be different on different compilers, but for example INT16_MIN+1 to INT16MAX-1 is too wide on either of the compilers I have tried. It always fails starting at line 448:

      constexpr bool valid[sizeof...(I)] = {is_valid<E, value<E, Min, IsFlags>(I)>()...};
      constexpr std::size_t count = values_count(valid);
    
      if constexpr (count > 0) {
        E values[count] = {};
        for (std::size_t i = 0, v = 0; v < count; ++i) {
          if (valid[i]) {
            values[v++] = value<E, Min, IsFlags>(i);
          }
        }
    

    I realize that a wide interval may quite inefficient for a compiler. It might be useful to put a warning in the Limitations section of the docs and suggest what a reasonable limit might be.

    question 
    opened by rpatters1 18
  • Proposed enhancement to enum_name

    Proposed enhancement to enum_name

    EDIT: Thinking a bit harder, it might be better that this functionality be moved to a new method, perhaps called enum_name_of_bits_set or something and leave enum_name alone...

    Hi, I have no clue about github or pull requests, so I thought I'd write my proposed enhancement to enum_name here...

    If an enum contains bitfield values, there exists already the ability to bitwise AND and OR the values together to create flag fields. But there is no way to print such a flag.

    Example :

    using namespace magic_enum;
    using namespace magic_enum::bitwise_operators;
    
    enum Rooms { None = 0, Bedroom = 1 << 0, Lounge = 1 << 1, Kitchen = 1 << 2 };
    Rooms toPaint = Rooms::Bedroom | Rooms::Kitchen;
    
    std::cout << "My wife want me to paint these : " << enum_name<Rooms>(toPaint) << '\n';
    

    Desired output : My wife want me to paint these : Bedroom|Kitchen

    Actual output : My wife want me to paint these :

    Here is a replacement

        // Returns string enum name from enum value.
        // If enum value does not have name or value out of range, returns empty string.
        template <typename E>
        [[nodiscard]] constexpr auto enum_name(E value) noexcept 
        -> detail::enable_if_enum_t<E, std::string_view>
        {
            //  Begin Changes ga2k 2020-05-29
    
            //  return enum_traits<E>::name(value);
    
            auto n = enum_traits<E>::name(value);
            if (!n.empty())
                return n;
    
            //  See if there is a name for each bit set in value. 
            //  If so, concatenate them with '|' separator
    
            //  First find largest value
    
            constexpr auto values = enum_values<E>();
            constexpr auto largest = values[values.size() - 1];
            static std::string s;
    
            for (int b = 0; (1 << b) <= largest; ++b)
            {
                if ((value & (1 << b)) == (1 << b))	// This bit is set in value
                {
                    auto n2 = enum_traits<E>::name(static_cast<E>(1 << b));
    
                    if (n2.empty())
                        return n2;	// No name at this bt value : not a bitfield value, so bail
    
                    if (!s.empty())
                    {
                        s += '|';
                    }
    
                    s += n2;
                }
            }
    
            return static_cast<std::string_view>(s);
                
            // End Additions ga2k 2020-05-29
        }
    

    Thoughts?

    enhancement help wanted 
    opened by ga2k 18
  • Intellisense hangs forever when using magic_enum since 0.6.1 on x86 projects

    Intellisense hangs forever when using magic_enum since 0.6.1 on x86 projects

    Ctrl+clicking on anything in my project stalls waiting for intellisense to complete if I include magic_enum 0.6.1 or newer. Version 0.6.0 doesn't have this problem.

    Edit: Only happens on 32bit projects.

    Tested in Visual Studio 2019 and Visual Studio 2017.

    invalid 
    opened by albertvaka 14
  • O(1) conversion to location of enum in enum_values

    O(1) conversion to location of enum in enum_values

    Is there a way to do O(1) conversion of Color::BLUE to 1 (rather than 4, as enum_integer would do)?

    Motivation: I have an enum generated by an external tool which may have gaps in it, and I need to pack the enums into a contiguous sequence of integers starting at 0 (so that I can more efficiently store it in memory somewhere else). I don't need this packing to be stable across invocations of the program, but it should be stable within the program.

    enhancement 
    opened by ezyang 14
  • Compilation error using clang

    Compilation error using clang

    Hi I recently switched my project from using gcc to clang, and ran into this error:

    _deps/magic_enum_content-src/include/magic_enum.hpp:116:18: error: constexpr variable 'prefix' must be initialized by a constant expression
      constexpr auto prefix = name.find_last_of(" :,-)") + 1;
                     ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    Clang version:

    clang version 8.0.0 (Fedora 8.0.0-1.fc30)
    Target: x86_64-unknown-linux-gnu
    

    Gcc version:

    g++ (GCC) 9.1.1 20190503 (Red Hat 9.1.1-1)
    

    Flag list:

                              -Wall
                              -Wextra
                              -Werror
                              -Wnon-virtual-dtor
                              -Wold-style-cast
                              -Woverloaded-virtual
                              -Wsign-conversion
                              -Wconversion
                              -Wnull-dereference
                              -Wformat=2
                              -Wdouble-promotion
                              -fasynchronous-unwind-tables
                              -fstack-protector
                              -fstack-protector-strong
                              -fPIC
                              -pipe
                              -fsanitize=address
                              -fsanitize=undefined
                              -g
                              -fdiagnostics-color=always
                              -fno-omit-frame-pointer
    

    Thank you for your work in this library, please let me know if I can provide more info.

    bug help wanted 
    opened by khoitd1997 14
  • Support no default value enum_switch

    Support no default value enum_switch

    would it be possible to support enum_switch the way that we're used to use overload pattern with std::visit? e.g

    return magic_enum::enum_switch( overloaded{
               []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; },
               []( auto arg ) -> int { /* handle the rest */ throw notimplemented; /* or just return sth */ }
    });
    

    instead of

    return magic_enum::enum_switch( overloaded{
               []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; },
               []( auto arg ) -> int { /* handle the rest */ throw notimplemented; /* or just return sth */ }
    }, /*redundant default*/ int(2));
    
    // or probably worse
    
    auto r = magic_enum::enum_switch(
               []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; }
               , int(2)
    );
    
    if( r == 2 ) throw notimplemented;
    

    I think forcing adding default Result produces boilerplate.

    enhancement 
    opened by Sarna555 12
  • constexpr Hashing Enum ?

    constexpr Hashing Enum ?

    Essentially, a meaningful association between the stringified enum key and the integral value it maps to is desirable.

    When communicating an enum across an interface, too often we end up communicating values that mean absolutely nothing. If they were, instead, the result of passing a string into a constexpr hashing function, then that would add a strong association and more value to the integral value. Such an enum wrapper (or utility function) could be very useful for interfaces.

    Though for our purposes, it would be most helpful to also have a C# companion library with similar functionality at the other side of the interface--the hashing function in particular.

    Just an idea, let me know what you think!

    opened by calebarist 11
  • magic enum static_asserts on an enum value of 129

    magic enum static_asserts on an enum value of 129

    I ran into this with 0.7.2, then upgraded to 0.7.3. Both have this issue. I use git and tags, so this was with tag "v0.7.3".

    Consider the following snippet:

    #include <magic_enum.hpp>
    
    enum Errors {
      SE_EKEYREJECTED = 129,
    };
    
    std::string to_string(Errors error)
    {
      auto sv = magic_enum::enum_name(error);
      return std::string{sv};
    }
    
    int main()
    {
    }
    

    When compiling, you get:

    include/magic_enum.hpp:407:21: error: static assertion failed: magic_enum::enum_range detects enum value larger than max range size.
      407 |       static_assert(!is_valid<E, value<E, lhs + 1, IsFlags>(0)>(), "magic_enum::enum_range detects enum value larger than max range size.");
    include/magic_enum.hpp:407:21: note: ‘! magic_enum::detail::is_valid<Errors, SE_EKEYREJECTED>()’ evaluates to false
    

    Using a value of 128 or 130 compiles fine. Having other enums in there does not make a difference.

    question 
    opened by CarloWood 11
  • compile-time optimization

    compile-time optimization

    The code is quite heavy on compile-time and could use some optimizations (e.g. every enum_cast takes 1s to instantiate in my test). clang got improved recently to cover constexpr evaluations in time traces which will come in handy: https://reviews.llvm.org/D136022.

    Half of the parsing time alone is spent on constexpr_switch for example, and is_flags_enum is very heavy to instantiate because it calls values. Here's the test-cpp17 time trace generated with -ftime-trace -ftime-trace-granularity=100, can be viewed with https://ui.perfetto.dev.

    opened by Trass3r 10
  • 0.8.2 breaks `enum_name` with custom ranges?

    0.8.2 breaks `enum_name` with custom ranges?

    It seems like the newest optimizations in 0.8.2 break enum_name in GCC and Clang. Here's a minimal complete verifiable example:

    MVCE

    I've also prepared a gist.

    The MVCE needs the following file structure:

    CMakeLists.txt
    enum.h
    enum.cc
    magic_enum.hpp
    main.cc
    main_with_range.cc
    

    CMakeLists.txt

    The CMakeLists.txt specifies the language standard and three targets:

    • a enum library, which uses magic_enum internally but doesn't expose it via its header/interface
    • a mve, which uses the aforementioned enum library, but not the magic_enum.hpp header
    • a mve_bad, which uses the aforementioned enum library and magic_enum.hpp header as well as enum_range
    cmake_minimum_required(VERSION 3.15)
    project (mve LANGUAGES CXX)
    set(CMAKE_CXX_STANDARD 17)
    
    option(ENABLE_FIX "Enable MAGIC_ENUM_ENABLE_HASH" OFF)
    if(ENABLE_FIX)
        add_compile_definitions(MAGIC_ENUM_ENABLE_HASH)
    endif()
    
    add_library(enum STATIC enum.cc)
    
    add_executable(mve main.cc)
    target_link_libraries(mve enum)
    
    add_executable(mve_bad main_with_range.cc)
    target_link_libraries(mve_bad enum)
    

    enum.h

    enum.h contains a single enum with values that are outside of magic_enum's default range, i.e. flag::high with 500, as well as a declaration for a string_view-yielding function:

    #ifndef EXAMPLE_ENUM_H
    #define EXAMPLE_ENUM_H
    
    #include <string_view>
    
    enum class flag
    {
        low = 0,
        high = 500,
    };
    
    std::string_view to_string(flag);
    
    #endif // EXAMPLE_ENUM_H
    

    Note that magic_enum is explicitly not a

    enum.cc

    This file contains a customize::enum_range call to work around the known limitations. It also contains the implementation of the aforementioned to_string function, which calls magic_enum::enum_name within the same file:

    #include "enum.h"
    #include "magic_enum.hpp"
    
    template <>
    struct magic_enum::customize::enum_range<flag>
    {
        static constexpr int min = static_cast<int>(flag::low);
        static constexpr int max = static_cast<int>(flag::high);
    
        static_assert(static_cast<uint64_t>(max) - static_cast<uint64_t>(min) < std::numeric_limits<uint16_t>::max(),
                      "magic_enum only supports names for the uint16_t range.");
    };
    
    std::string_view to_string(flag f){
        return magic_enum::enum_name(f);
    }
    

    main.cc

    Now, this is the "working" case. Both lines return exactly what you would expect:

    #include <iostream>
    
    #include "enum.h"
    #include "magic_enum.hpp"
    
    int main() {
        std::cout << to_string(flag::low) << std::endl;  // prints "low", as expected
        std::cout << to_string(flag::high) << std::endl; // prints "high", as expected
    }
    

    main_with_range.cc

    But as soon as you use magic_enum::enum_values<enum_type>(), the customization in the implementation file gets ignored:

    #include <iostream>
    
    #include "enum.h"
    #include "magic_enum.hpp"
    
    int main() {
        for (auto f : magic_enum::enum_values<flag>()) {
            std::cout << to_string(f) << std::endl;  // ⚠prints only "low"
        }
        std::cout << "---\n";
    
        std::cout << "low:  " << to_string(flag::low) << std::endl;  // prints only "low:  low"
        std::cout << "high: " << to_string(flag::high) << std::endl; // ⚠ `to_string(flag::high)` returns ""!
    }
    

    I've tried main_with_range.cc with multiple versions of magic_enum and multiple compilers:

    | magic_enum Version | MSVC 2022 | Clang/LLVM 11 | GCC 9.4 | |---------|---------|---------|---------| | 0.7.3 | Works ✔| Works ✔| Works ✔| | 0.8.0 | Works ✔| Works ✔| Works ✔| | 0.8.1 | Works ✔| Works ✔| Works ✔| | 0.8.2 | Works ✔| Breaks ❌| Breaks ❌| | 0.8.2 (with MAGIC_ENUM_ENABLE_HASH)* | Works ✔| Works ✔ | Works ✔|

    * enabled via cmake -DENABLE_FIX=ON

    Conclusion

    It seems like the behavior of magic_enum::enum_name changes if magic_enum::enum_values has been used anywhere else. Given that it worked in several previous versions, this seems like a defect within 0.8.2., but I'm not entirely sure.

    Note that main_with_range.cc works fine if one includes enum.cc instead of enum.h, but I can't count on all downstream users and developers to redefine the magic_enum::customize::enum_range specialization.

    bug 
    opened by bkaestner 2
  • Compilation fails for Clang 14/15 with libstdc++ 11/12

    Compilation fails for Clang 14/15 with libstdc++ 11/12

    I think I'm stumbling on an issue with constexpr:

    ...
    /home/dmg/.cpm/magic_enum/85381df3eba66591cca3b1dbbecd395633b95ee6/include/magic_enum.hpp:571:23: note: declared here
    inline constexpr bool is_flags_v = is_flags_enum<E>();
    

    From what I can tell the project builds fine when using the following combinations:

    • g++ with "bundled" libstdc++
    • clang++ with libc++
    • clang++ with libstdc++ 10

    Building fails when using:

    • Clang 14/15 with libstdc++ 11/12

    Is this a known limitation that I can workaround in the mean while?

    opened by damageboy 2
  • Unexpected behavior of enum_for_each for bitmasked enums

    Unexpected behavior of enum_for_each for bitmasked enums

    enum EnumTest
    {
    	A = 0,
    	B = 1 << 0,
    	C = 1 << 1,
    	D = 1 << 2,
    	E = 1 << 3,
    	F = 1 << 4,
    	G = 1 << 5,
    	H = 1 << 6,
    	I = 1 << 7,
    	J = 1 << 8,
    	K = 1 << 9,
    	L = B | C | E | G,
    };
    std::string result="";
    
    magic_enum::enum_for_each<EnumTest>([&](EnumTest t) {
    	std::string n = std::string(magic_enum::enum_name(t));
    	result.append(n);
    });
    
    printf("%s", result.c_str());
    
    ABCDEFGLHI
    

    J and K are missing and the order is mixed

    enum EnumTest
    {
    	A = 0,
    	B = 1 << 0,
    	C = 1 << 1,
    	D = 1 << 2,
    	E = 1 << 3,
    	F = 1 << 4,
    	G = 1 << 5,
    	H = 1 << 6,
    	I = 1 << 7,
    	J = 1 << 8,
    	K = 1 << 9,
    	// L = B | C | E | G, // <- Remove
    };
    std::string result="";
    
    magic_enum::enum_for_each<EnumTest>([&](EnumTest t) {
    	std::string n = std::string(magic_enum::enum_name(t));
    	result.append(n);
    });
    
    printf("%s", result.c_str()); 
    
    BCDEFGHIJK
    

    A is missing

    opened by cr545l 3
  • Support cartesian product for enum_switch

    Support cartesian product for enum_switch

    Not so good but showing some use case example

    enum class MyType {
        INT2,
        INT4,
        INT8,
        FLOAT4,
        FLOAT8
    };
    
    struct MyData {
        void * data;
        MyType type;
    };
    
    auto var1 = init_my_data(10, MyType::INT4);
    auto var2 = init_my_data(10.23, MyType::FLOAT4);
    
    auto switcher = overloaded{
        [&]( magic_enum::enum_constant<MyType::INT4>, magic_enum::enum_constant<MyType::FLOAT4> ) {
            float result = *static_cast<int*>(var1.data) + *static_cast<float*>(var2.data);
            return init_my_type( result, MyType::FLOAT4 );
        },
        []( auto, auto ) { throw notimplemented; }
    };
    enum_switch( switcher, var1.type, var2.type );
    

    It's similar to what std::visit is doing with std::variant and cartesian product. Right now I think you need to add enum_switch in enum_switch to achive it and that imo produces boilerplate code.

    enhancement 
    opened by Sarna555 7
  • nested magic_enum::enum_switch -- failed on msvc?

    nested magic_enum::enum_switch -- failed on msvc?

    https://gist.github.com/Korsar13/5c171d0cd0b47d62276cac07b6b6a184

    compiled by clang, prints

    convert from char to char
    convert from char to int
    convert from char to float
    convert from int to char
    convert from int to int
    convert from int to float
    convert from float to char
    convert from float to int
    convert from float to float
    

    msvc compilation fails, mm.cpp(39): error C2893: Failed to specialize function template 'void convert_tmpl(const TSrc *,TDst *,size_t)'

    help wanted invalid 
    opened by Korsar13 3
Releases(v0.8.2)
  • v0.8.2(Dec 9, 2022)

    Release v0.8.2

    • Compile-time optimization (https://github.com/Neargye/magic_enum/issues/219, https://github.com/Neargye/magic_enum/issues/207)
    • Add option MAGIC_ENUM_ENABLE_HASH to generate a hash switch, this need more memory and compile-time but functions like 'enum_name', 'enum_switch', etc will have O(1) complexity
    • Add a separate header for enum_switch
    • Add support no default value enum_switch (https://github.com/Neargye/magic_enum/issues/199)
    • Fix build clang-16(https://github.com/Neargye/magic_enum/issues/204)
    • Fix VS2022 IntelliSence Error (https://github.com/Neargye/magic_enum/issues/198)
    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(60.72 KB)
    magic_enum_format.hpp(3.52 KB)
    magic_enum_fuse.hpp(3.65 KB)
    magic_enum_switch.hpp(7.05 KB)
  • v0.8.1(Aug 4, 2022)

  • v0.8.0(May 10, 2022)

    Release v0.8.0

    • [breaking changes] New enum-flags API. Added is_flags option in enum_range.

    • [breaking changes] New customize. (#166)

    • Add enum_fuse - fusing function in separate header.

    • Add support for non-ASCII characters (UNIX/Linux) (#95)

    • Add enum_switch and enum_for_each.

    • Add istream operators.

    • Add compile-time enum_index and enum_value.

    • Add support gcc8 with defined MAGIC_ENUM_NO_CHECK_SUPPORT. (#137)

    • Many small fixes underflow in out of range check, bool enum, etc.

    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(55.05 KB)
    magic_enum_fuse.hpp(3.65 KB)
  • v0.7.3(Jun 21, 2021)

    Release v0.7.3

    • Add detect values out of range and fail compilation (#70)
    • Add ability to include external configuration header (#86)
    • Fix std::array in some cases is missing constexpr on some of it's functions (#76)
    • Fix using leak (#80)
    • Fix hard error if enum is empty or non-reflected (#79)
    • Fix some warning
    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(41.35 KB)
  • v0.7.2(Dec 23, 2020)

  • v0.7.1(Dec 2, 2020)

  • v0.7.0(Oct 14, 2020)

    Release v0.7.0

    • Add namespace flags with API for enum-flags https://github.com/Neargye/magic_enum/issues/40
    • Add syntax for defining custom enum names https://github.com/Neargye/magic_enum/issues/50
    • Add way to switch std::optional, std::string and std::string_view to custom type https://github.com/Neargye/magic_enum/issues/45
    • Add support for bazel https://github.com/Neargye/magic_enum/pull/56
    • Add MAGIC_ENUM_OPT_INSTALL option in CMakeLists.txt https://github.com/Neargye/magic_enum/pull/54
    • Add macro MAGIC_ENUM_SUPPORTED_ALIASES to check whether enum-aliases supported https://github.com/Neargye/magic_enum/issues/36
    • Improve API usability https://github.com/Neargye/magic_enum/issues/55
    • Fix build error in clang https://github.com/Neargye/magic_enum/issues/53
    • [breaking changes] enum_range moved to namespace magic_enum::customize https://github.com/Neargye/magic_enum/pull/52
    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(40.17 KB)
  • v0.6.6(Jun 5, 2020)

    Release v0.6.5

    • Fix compiler check https://github.com/Neargye/magic_enum/issues/39
    • Fix hangs Intellisense https://github.com/Neargye/magic_enum/issues/34
    • Fix compatibility with legacy C-Style APIs https://github.com/Neargye/magic_enum/issues/37
    • Add comparison predicate for enum_cast https://github.com/Neargye/magic_enum/issues/35
    • Add enum_contains https://github.com/Neargye/magic_enum/pull/30
    • Add enum_type_name https://github.com/Neargye/magic_enum/issues/25
    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(27.10 KB)
  • v0.6.5(Jan 31, 2020)

  • v0.6.4(Dec 30, 2019)

  • v0.6.3(Oct 18, 2019)

  • v0.6.2(Oct 8, 2019)

    Release v0.6.2

    • Fix cvref regression, fix https://github.com/Neargye/magic_enum/pull/16.

    • Add documentation.

    • Improve enum_value for dense enums.

    • Add check if the enum is a forward declaration or valid enum_range::max and enum_range::min, fix #15.

    • Add macro MAGIC_ENUM_SUPPORTED to check compiler support.

    • Caching enum_values, enum_names, enum_entries.

    • Remove is_fixed_enum.

    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(23.29 KB)
  • v0.6.1(Sep 29, 2019)

    Release v0.6.1

    • Less bin size and overhead reduction, thanks @rollbear. Fix https://github.com/Neargye/magic_enum/issues/14.

    • Fix type cast for unsigned enum.

    • More SFINAE-friendly.

    • Add enum_index. Fix https://github.com/Neargye/magic_enum/issues/12.

    • Add enum_traits.

    • Add error msg unsupported compiler, use MAGIC_ENUM_NO_CHECK_SUPPORT to suppress supported compiler check.

    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(23.30 KB)
  • v0.6.0(Jul 27, 2019)

    Release v0.6.0

    • Fix build fail with sanitize, see https://github.com/Neargye/magic_enum/issues/6

    • Fix Syntax Error caused by "Windows.h", see https://github.com/Neargye/magic_enum/issues/7

    • Fix implicit conversion changes signedness.

    • Improving compile times.

    • Improve ostream operators for enums.

    • Add bitwise operators for enums.

    • Add is_fixed_enum, underlying_type.

    • [breaking changes] change magic_enum::ops to magic_enum::ostream_operators

    Source code(tar.gz)
    Source code(zip)
    magic_enum.hpp(18.91 KB)
Owner
Daniil Goncharov
Daniil Goncharov
std::tuple like methods for user defined types without any macro or boilerplate code

Boost.PFR This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other std::tuple like me

Antony Polukhin 145 Dec 18, 2022
C++ compile-time enum to string, iteration, in a single header file

Better Enums Reflective compile-time enum library with clean syntax, in a single header file, and without dependencies. In C++11, everything can be us

Anton Bachin 1.4k Dec 27, 2022
Header-only, non-intrusive and macro-free runtime reflection system in C++

Header-only runtime reflection system in C++ The reflection system was born within EnTT and is developed and enriched there. This project is designed

Michele Caini 452 Jan 4, 2023
A compiling time static reflection framework for C++

static_reflect This is a fully compiling time static reflection lightweight framework for C++. It provides a very rich compile-time reflection functio

null 13 Dec 25, 2022
A modern compile-time reflection library for C++ with support for overloads, templates, attributes and proxies

refl-cpp v0.12.1 Documentation refl-cpp encodes type metadata in the type system to allow compile-time reflection via constexpr and template metaprogr

Veselin Karaganev 783 Dec 31, 2022
C++ Reflection Parser / Runtime Skeleton

C++ Reflection Preface I worked on a complete reflection pipeline starting in the summer of 2015 for a game project / editor. My intent by creating th

Austin Brunkhorst 555 Dec 24, 2022
C++ reflection library with Lua binding, and JSON and XML serialisation.

Ponder Linux & OSX: - Windows: Currents status: 3.2-alpha. API is unstable as features added/changed. New: Version 3 V1 replaced Boost with C++11. V2

Bill Quith 573 Dec 28, 2022
C++ Reflection Library

!New Release - 0.9.6! RTTR C++ Reflection Library RTTR stands for Run Time Type Reflection. It describes the ability of a computer program to introspe

rttr.org 2.5k Jan 3, 2023
A miniature library for struct-field reflection in C++

visit_struct A header-only library providing structure visitors for C++11 and C++14. Motivation In C++ there is no built-in way to iterate over the me

null 393 Dec 12, 2022
Customizable C++17 Runtime Reflection Library

Refureku Check the Wiki for more documentation and use examples! Refureku is a powerful C++17 RTTI free runtime reflection library based on Kodgen. It

Julien SOYSOUVANH 177 Dec 28, 2022
A miniature library for struct-field reflection in C++

visit_struct A header-only library providing structure visitors for C++11 and C++14. Motivation In C++ there is no built-in way to iterate over the me

null 397 Jan 7, 2023
Nameof operator for modern C++, simply obtain the name of a variable, type, function, macro, and enum

_ _ __ _____ | \ | | / _| / ____|_ _ | \| | __ _ _ __ ___ ___ ___ | |_ | | _| |

Daniil Goncharov 1.5k Jan 4, 2023
Nameof operator for modern C++, simply obtain the name of a variable, type, function, macro, and enum

_ _ __ _____ | \ | | / _| / ____|_ _ | \| | __ _ _ __ ___ ___ ___ | |_ | | _| |

Daniil Goncharov 1.5k Jan 8, 2023
std::tuple like methods for user defined types without any macro or boilerplate code

Boost.PFR This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other std::tuple like me

Antony Polukhin 145 Dec 18, 2022
std::tuple like methods for user defined types without any macro or boilerplate code

Boost.PFR This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other std::tuple like me

Boost.org 1.1k Dec 23, 2022
C++ compile-time enum to string, iteration, in a single header file

Better Enums Reflective compile-time enum library with clean syntax, in a single header file, and without dependencies. In C++11, everything can be us

Anton Bachin 1.4k Dec 27, 2022
A C++14 macro to get the type of the current class without naming it

self_macro C++14 header only library that exposes a macro that creates a type alias for the current class without naming it. Also exposes macros that

Mital Ashok 10 Dec 12, 2022
Header-only, non-intrusive and macro-free runtime reflection system in C++

Header-only runtime reflection system in C++ The reflection system was born within EnTT and is developed and enriched there. This project is designed

Michele Caini 452 Jan 4, 2023