{"id":49530296,"url":"https://github.com/ZXShady/enchantum","last_synced_at":"2026-05-04T18:01:00.167Z","repository":{"id":289313984,"uuid":"967807282","full_name":"ZXShady/enchantum","owner":"ZXShady","description":"Faster enum reflection for C++17 since I don't want to wait for C++26 reflection.","archived":false,"fork":false,"pushed_at":"2026-04-24T21:13:30.000Z","size":538,"stargazers_count":122,"open_issues_count":1,"forks_count":11,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-04-24T23:20:16.275Z","etag":null,"topics":["c-plus-plus","cpp","cpp17","cpp20","enum","enum-to-string","header-only","is-bitflag-enum","metaprogramming","no-dependencies","reflection","reflection-library","serialization","string-to-enum","templates"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZXShady.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-17T03:16:02.000Z","updated_at":"2026-04-24T21:13:38.000Z","dependencies_parsed_at":"2025-04-22T17:33:40.349Z","dependency_job_id":"7eab4201-ce5e-4a12-9922-35b8ff30a444","html_url":"https://github.com/ZXShady/enchantum","commit_stats":null,"previous_names":["zxshady/enchantum"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/ZXShady/enchantum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZXShady%2Fenchantum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZXShady%2Fenchantum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZXShady%2Fenchantum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZXShady%2Fenchantum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZXShady","download_url":"https://codeload.github.com/ZXShady/enchantum/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZXShady%2Fenchantum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32618391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-plus-plus","cpp","cpp17","cpp20","enum","enum-to-string","header-only","is-bitflag-enum","metaprogramming","no-dependencies","reflection","reflection-library","serialization","string-to-enum","templates"],"created_at":"2026-05-02T07:00:28.167Z","updated_at":"2026-05-04T18:01:00.141Z","avatar_url":"https://github.com/ZXShady.png","language":"C++","funding_links":[],"categories":["Reflection"],"sub_categories":[],"readme":"# Enchantum\n\n**Enchantum** (short for \"enchant enum\") is a modern **C++17** header-only library for **compile-time enum reflection**. It provides fast, lightweight access to enum values, names, and bitflags all without macros or boilerplate.\n\n\u003e Every year, countless turtles perish due to the pollution caused by slow, bloated build times.  \n Save the turtles — and your compile times — by switching to enchantum!\n\n\u003csup\u003e\u003csub\u003eSource: I made it up.\u003c/sup\u003e\u003c/sub\u003e\n\nKey Features\n\n  - Macro-free and non-intrusive boilerplate-free reflection\n\n  - Fast compile times (benchmarked below)\n\n  - Most efficient binary size wise.\n  \n  - 0 Allocations\n\n  - Supports:\n       -  Scoped enums\n       -  Unscoped C enums\n       -  Sparse enums\n       -  Bitflags\n       -  Iteration over values,names and `[enum, name]` pairs.\n       -  `string \u003c=\u003e enum` conversions\n       -  `enum \u003c=\u003e index` conversions\n       -  enum validation functions like `cast` and `contains`\n       -  enum aware containers adaptors like `enchantum::bitset` and `enchantum::array`\n  - Extra features like:\n      - Functions that output enums with their scope\n      - Optional null terminator disabling\n      - Optional prefix stripping for C-style enums\n      - `0` values are reflected for bitflag enums \n\n[Simple Examples](#simple-examples)\n\n[Why another enum reflection library?](#why-another-enum-reflection-library)\n\n[Features](docs/features.md)\n\n[Benchmarks](#benchmarks)\n\n[Limitations](docs/limitations.md)\n\n[CMake Integration](#cmake-integration)\n\nTested locally on Windows 10 with:\n- Visual Studio 2022 (19.44)\n- GCC 14.2.0\n- Clang 20.1.2\n\nCompiler Support: (Look at [CI](https://github.com/ZXShady/enchantum/actions))\n  - GCC \u003e= 9 \n  - Clang \u003e= 8\n  - MSVC \u003e= 19.24 VS16.4 (lower verions tested through godbolt)\n  - Resharper \u003e= 2023\n\nTested through basic tests on godbolt since I could not install it on CI, so support for them may not be the best.\n  - ICX \u003e= 2021.1.2 (Tested through godbolt [test link](https://godbolt.org/z/5naTha56K))\n  - NVC++ \u003e= 22.7 (minimum on godbolt [test link](https://godbolt.org/z/xr7xr6Y6v))\n\n---\n\n\u003e [!IMPORTANT]\n\u003e Be sure to read [Limitations](docs/limitations.md) before using enchantum.\n\n## Simple Examples\n\n* to string\n```cpp\n#include \u003cenchantum/enchantum.hpp\u003e // to_string\n#include \u003cenchantum/iostream.hpp\u003e // iostream support\nenum class Music { Rock, Jazz , Metal };\n\nint main() \n{\n  auto music = Music::Rock;\n  std::string_view music_name =  enchantum::to_string(music);\n  // music_name == \"Rock\"\n\n  using namespace enchantum::iostream_operators;\n  std::cout \u003c\u003c music;\n  // Prints Rock\n}\n```\n\n* from strings\n```cpp\n#include \u003cenchantum/enchantum.hpp\u003e // cast\nenum class Music { Rock, Jazz , Metal };\nint main() \n{\n  // case sensitive\n  std::optional\u003cMusic\u003e music = enchantum::cast\u003cMusic\u003e(\"Jazz\");\n  if(music.has_value()) // check if cast succeeded\n  {\n    // *music == Music::Jazz\n  }\n  // pass a predicate taking two string views\n  music = enchantum::cast\u003cMusic\u003e(\"JAZZ\",[](char x,char y){\n      using UC = unsigned char;\n      return std::tolower(UC(x)) == std::tolower(UC(y));      \n  });\n  if(music.has_value()) {\n      // *music == Music::Jazz\n  }\n}\n```\n\n* index into enums\n```cpp\n#include \u003cenchantum/enchantum.hpp\u003e // index_to_enum and enum_to_index\nenum class Music { Rock, Jazz , Metal };\n\nint main() \n{\n  // case sensitive\n  std::optional\u003cMusic\u003e music = enchantum::index_to_enum\u003cMusic\u003e(1); // Jazz is the second enum member\n  if(music.has_value()) // check if index is not out of bounds\n  {\n    // *music == Music::Jazz\n    std::optional\u003cstd::size_t\u003e index = enchantum::enum_to_index(*music);\n    // *index == 1\n  }\n}\n```\n\n* iteration\n```cpp\n#include \u003cenchantum/enchantum.hpp\u003e // entries,values and names \nenum class Music { Rock, Jazz , Metal };\n\nint main() \n{\n  // Iterate over values\n  for(Music music : enchantum::values_generator\u003cMusic\u003e)\n    std::cout \u003c\u003c static_cast\u003cint\u003e(music) \u003c\u003c \" \";\n  // Prints \"0 1 2\"\n\n  // Iterate over names\n  for(std::string_view name : enchantum::names_generator\u003cMusic\u003e)\n    std::cout \u003c\u003c name \u003c\u003c \" \";\n  // Prints \"Rock Jazz Metal\"\n\n  // Iterate over both!\n  for(const auto [music,name] : enchantum::entries_generator\u003cMusic\u003e)\n    std::cout \u003c\u003c name \u003c\u003c \" = \" \u003c\u003c static_cast\u003cint\u003e(music) \u003c\u003c \"\\n\";\n  \n  // Prints \n  // Rock = 0\n  // Jazz = 1\n  // Metal = 2\n}\n```\n\nLook at [Features](docs/features.md) for more information.\n\n\n## Why Another Enum Reflection Library?\n\nThere are several enum reflection libraries out there — so why choose **enchantum** instead of [magic_enum](https://github.com/Neargye/magic_enum), [simple_enum](https://github.com/arturbac/simple_enum), or [conjure_enum](https://github.com/fix8mt/conjure_enum)?\n\n\n### magic_enum\n\n**Pros**\n- Macro-free (non intrusive).\n- No modifications needed for existing enums.\n- Allows specifying ranges for specific enums when needed.\n- Supports C++17.\n- Nicer compiler errors.\n- Supports wide strings.\n- Efficient executable binary size.\n- Null terminated strings.\n- 0 Allocations\n\n**Cons**\n- Compile times grow significantly with larger `MAGIC_ENUM_MAX_RANGE`.\n- No warnings for not fully reflected enums.\n\n### conjure_enum\n\n**Pros**\n- Macro-free (non intrusive)\n- Uses C++20\n\n**Cons**\n\n- Slow compilation speed\n- Bigger executable sizes\n- Non optimal algorithms\n- Allocations\n- No warnings for not fully reflected enums.\n\n### simple_enum\n\n**Pros**\n- Faster compile times.\n- Functor based API.\n- 0 Allocations\n\n**Cons**\n- Requires specifying enum `first`/`last` values manually (intrusive, doesn't work well with third-party enums)\n- Compile time slows down with large enum ranges\n- Big binary size bloat.\n- No support for bitflags yet.\n- No support for null terminated strings.\n- No warnings for not fully reflected enums.\n\n### enchantum\n\n**Pros**\n- Macro-free (non intrusive)\n- Allows specifying ranges for specific enums when needed\n- Compiles fast.\n- Supports C++17.\n- Clean and Simple Functor based API `enchantum::to_string(E)` no `enchantum::to_string\u003cE::V\u003e()` since compile times are fast.\n- Features like disabling null termination if not needed and specifying common enum prefix for C style enums, and reflect '0' values for bit flag enums.\n- Supports all sort of enums (scoped,unscoped,C style unfixed underlying type,anonymous namespaced enums, enums with commas in their typename,etc..)\n- Most efficient object binary size and executable size.\n- Null terminated strings.\n- 0 Allocations\n- Compiler errors for not fully reflected enums.\n\n**Cons**\n- No support for wide strings.\n\n---\n\n## Benchmarks\n\n### Summary\n\n**enchantum** significantly reduces compile times and binary sizes in enum reflection projects. In my own project (which uses [libassert](https://github.com/jeremy-rifkin/libassert) and enum reflection for configuration), switching from `magic_enum` reduced full rebuild times from about 2 minutes to 1 minute and 26 seconds (34 seconds difference).\nI also tried compiling my project using [-2048,2048] as my range and it took 1 minute and 46 seconds! that's still less than `magic_enum` by default while having **16x** the default range.\n\n\nEach compile time benchmark was run 10 times and averaged unless noted otherwise.\n`range` is `ENCHANTUM_MAX_RANGE` and `MAGIC_ENUM_RANGE_MAX`, for `simple_enum` it is defining `last` and `first` with the range because I could not find a macro for this, this is technically misuse of the library since it likes having these values close to the actual range but the comparisons would be unfair.\n\nThe enum members are from 0 to Count\n\n|      Test Case         | Small      | Big          | Large Range | Ideal Range |\n|------------------------|------------|--------------|-------------|-------------|\n| Number of Enums        | 200        | 32           | 200         | 100         |\n| Enum Reflection Range  | (-128,128) | (-256,256)   | (-1024,1024)| (0,50)      |\n| Enum members from 0 to | 16         | 200          | 16          |  50         |\n\n\n### Compile Time\nAll times in seconds (lower is better, bold is fastest). Compiled with `-O3` fir GCC and Clang while `/Ox` for MSVC. \n\n\"Timeout\" means it took more than 20 minutes and still did not finish\n\n**Notes**: numbers in `()` are with [`ENCHANTUM_CHECK_OUT_OF_BOUNDS_BY`](docs/features.md/#enchantum_check_out_of_bounds_by) set to the default which is `2`.\nin short terms it is extra compile time only checks against not fully reflected enums which can be disabled by setting it to `0`.\n\nConjure enum was compiled with `FIX8_CONJURE_ENUM_MINIMAL` macro defined.\n\n| Compiler    | Test Case   | `enchantum`     | `magic_enum` | `simple_enum` | `conjure_enum` |\n|-------------|-------------|-----------------|--------------|---------------|----------------|\n| **GCC**     | Small       | **6.0**  (9.3)  |  47          | 21.5          | 97.1           |\n|             | Big         | **2.7**  (4.6)  |  21          | 6.3           | 81.7           |\n|             | Large Range | **15.9** (45.1) |  Timeout     | 313           | Unknown        |\n|             | Ideal Range | 3        (4.2)  |  8.1         | **2.7**       | 46.8           |\n|                                                                            |                |\n| **Clang**   | Small       | **5.8**  (8.7)  |  47          | 14            | 66.8           |\n|             | Big         | **2.3**  (3.6)  |  18          | 4.4           | 52.9           |\n|             | Large Range | **15.1** (36.6) |  Timeout     | 96.3          | Timeout        |\n|             | Ideal Range | 2.9      (3.5)  |  8.7         | **2.3**       | 32             |\n|                                                                                             |\n| **MSVC**    | Small       | **15.8** (50.7) |  80          | 186           | ERROR          |\n|             | Big         | **8.8**  (13.6) |  37          | 32.1          | 244.9          |\n|             | Large Range | **85.3** (265.1)|  Timeout     | Timeout       | Timeout        |\n|             | Ideal Range | 5.8      (18.1) |  17.9        | **4.7**       | 95.7           |\n\n`conjure_enum` in \"Small\" test case caused the compiler to emit\n\n```js\nfatal error C1060: compiler is out of heap space\n```\n\n## Object File Sizes\n\nLower is better,bold is smallest, all measurements are in kilobytes.\n\n[A simple godbolt link for conjure_enum vs magic_enum vs enchantum difference in binary sizes](https://godbolt.org/z/cMvdEa65d) \ncould not get `simple_enum` in there since it does not have a single header version.\n\n\nClang is only currently measured.\n\n| Compiler    | Test Case   | `enchantum`  | `magic_enum` | `simple_enum` | `conjure_enum` |\n|-------------|-------------|--------------| ------------ |---------------|----------------|\n| **Clang**   | Small       | **275**      | 732          | 12070         | 779            |\n|             | Big         | **84**       | 1307         | 3847          | 1400           |\n|             | Large Range | **275**      | Unknown      | 98366         | Unknown        |\n|             | Ideal Range | **299**      | 1051         | 1233          | 1123           |\n\n\n**Note**:\nThe reason `simple_enum` is so big in object sizes is that it generates a huge table of all strings \nit does not do string optimizations like `enchantum` or `magic_enum` which leads to big object sizes\n\nIt stores this for example `\"auto se::f() [enumeration = A_0::A_0_4]\"`, the entire internal string instead of \nonly the part it needs (the \"A_0_4\" part)\nand this gets worse as the main enum name gets longer (e.g by putting the enums in a namespace), \nbut it also allows the library to do `O(1)` enum to string lookup for **any** enum, \nwhich I don't necessarily think is worth it and compile faster.\n\nAs for why `conjure_enum` although based on the same `magic_enum` implementation compile slower and larger binary sizes is due to unnecessary storing of enum namespaces in the binary. instead of storing `\"Value\"` it will store `\"Namespace::Enum::Value\"`.\n\n### Executable Sizes\n\nCompiled the object files into their own executable.\nLower is better, bold is smallest, all measurements are in kilobytes.\n\n| Compiler    | Test Case   | enchantum     | magic_enum     | simple_enum     | `conjure_enum` |\n|-------------|-------------|---------------|----------------|-----------------|----------------|\n| **Clang**   | Small       | **40**        | 95             | 2897            | 243            |\n|             | Big         | **56**        | 168            | 944             | 357            |\n|             | Large Range | **40**        | Unknown        | 23200           | Unknown        |\n|             | Ideal Range | **46**        | 134            | 308             | 305            |\n\n\n---\n\n# CMake Integration\n\nThe cmake file provides the target `enchantum::enchantum` since this library is header-only it is very simple to use you can copy and paste the files and add the include directory or use cmake and the library as a submodule. \n\n```cpp\nadd_subdirectory(\"third_party/enchantum\")\ntarget_link_libraries(your_executable enchantum::enchantum)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FZXShady%2Fenchantum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FZXShady%2Fenchantum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FZXShady%2Fenchantum/lists"}