https://github.com/arturbac/simple_enum
SimpleEnum: An Fast, Intuitive and Type-Safe C++ Enumeration Support Library
https://github.com/arturbac/simple_enum
code-safety cpp cpp-development-tools cpp-enumerations cpp-utilities cpp20 cpp23 enum enum-iteration enum-to-string enumeration-library header-only modern-cpp open-source programming-utilities serialization simple-enum type-safe
Last synced: about 2 months ago
JSON representation
SimpleEnum: An Fast, Intuitive and Type-Safe C++ Enumeration Support Library
- Host: GitHub
- URL: https://github.com/arturbac/simple_enum
- Owner: arturbac
- License: bsl-1.0
- Created: 2024-03-01T18:59:08.000Z (about 1 year ago)
- Default Branch: master
- Last Pushed: 2025-04-06T12:36:11.000Z (about 2 months ago)
- Last Synced: 2025-04-06T13:35:06.893Z (about 2 months ago)
- Topics: code-safety, cpp, cpp-development-tools, cpp-enumerations, cpp-utilities, cpp20, cpp23, enum, enum-iteration, enum-to-string, enumeration-library, header-only, modern-cpp, open-source, programming-utilities, serialization, simple-enum, type-safe
- Language: C++
- Homepage: https://arturbac.github.io/simple_enum/
- Size: 380 KB
- Stars: 33
- Watchers: 4
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
 [](https://github.com/arturbac/simple_enum/actions/workflows/ci.yml)
  
# simple_enum
## Features
- **Initial c++ module support** build mode, tested with clang 19 libc++ and clang 20 libc++,libstdc++
- **Bounded Enum Views**: Provides `enum_view` for iterating over bounded enumerations, leveraging `std::ranges::views`.
- **Enum to String and Back**: Supports conversion from enum to `std::string_view` and vice versa with minimal compile-time overhead.
- **Enumeration Indexing**: Offers `enum_index`, allowing for index retrieval of enum values based on compile-time metadata.
- **Glaze Integration**: Offers integration with [glaze json and glaze json rpc](https://arturbac.github.io/simple_enum/glaze_json_enum_support.html) latest supported glaze version is 4.2.2 and 4.4.0
- **Generic std::error_code** Integration: refer to [documentation](https://arturbac.github.io/simple_enum/generic_error_category.html)
- **std::format support** for enumerations : refer to [documentation](https://arturbac.github.io/simple_enum/std_format.html)
- **fmt::format support** for enumerations : refer to [documentation](https://arturbac.github.io/simple_enum/fmt_format.html)
- **and more**: take a look at [full documentation here](https://arturbac.github.io/simple_enum/)
```cpptemplate
concept enum_concept = std::is_enum_v;struct enum_name_t
{
template
static constexpr auto operator()(enum_type value) noexcept;
};
inline constexpr enum_name_t enum_name;// enum_view can exploit enum_name
constexpr auto view =
enum_view{}
| views::transform(enum_name);template
struct enum_cast_t
{
static constexpr auto operator()(std::string_view value) noexcept
-> expected;
template
inline constexpr enum_cast_t enum_cast{};struct enum_index_t
{
template
static constexpr auto
operator()(enum_type value) noexcept -> expected;
};inline constexpr enum_index_t enum_index;
```
## MotivationThe inception of this project was driven by the noticeable absence of an efficient `enum_name` meta-programming capability in existing solutions. This initiative showcases a proof of concept that `enum_name` can achieve efficiency when the enumeration is bounded. This allows for swift instantiation processes and ensures that the computational cost is directly proportional to the number of enumerations within an enum.
## Current Development Status
`simple_enum` is under active development on **Clang 18**, **GCC 14** and tested on **MSVC** with support on request down to **Clang 13** and**GCC 10**.
Minimum standard required by `simple_enum` is c++20, but it is tested and adopted to exploit c++23 features where it is possible.
## Planned features
- emum bitmasks support
- feature request are possible too
## Documentation[API documentation](https://arturbac.github.io/simple_enum/)
## Examples
```cpp
// There are 3 methods to set enum boundaries
//inside enum declaration using first last
enum struct enum_bounded { v1 = 1, v2, v3, first = v1, last = v3 };
// can be evaluated at compile time
static_assert(simple_enum::enum_name(enum_bounded::v2) == "v2");
// or at runtime
auto x0{enum_bounded::v2};
// enum_bounded has definitions for first and last so compile time is limited to processing meta info for declared
ut::expect(simple_enum::enum_name(x0) == "v2");enum struct enum_upper_bounded { v0, v1, v2, v3, last = v3 };
// enum_upper_bounded has definitions for last so compile time is limited to processing meta info for range
// [0..last] range only for upper bounded enum may be sparse enum used with not present first elements including 0
auto x1{enum_upper_bounded::v2};
ut::expect(simple_enum::enum_name(x1) == "v2");
// externally declaring boundary using adl found function
namespace some_user
{
enum struct enum_externaly_bounded { v0 = -15345953, v1, v2, v3 };consteval auto adl_enum_bounds(enum_externaly_bounded)
{
return simple_enum::adl_info{enum_externaly_bounded::v1, enum_externaly_bounded::v3};
}static void enum_externaly_bounded_using_adl()
{
auto x1{enum_externaly_bounded::v1};
std::cout << "enum_externaly_bounded " << simple_enum::enum_name(x1) << "\n";
}
} // namespace some_user
// externally declaring boundary using struct specialization
enum class std::memory_order : int
{
relaxed,
//[..]
seq_cst
};
template<>
struct simple_enum::info
{
static constexpr auto first = std::memory_order::relaxed;
static constexpr auto last = std::memory_order::seq_cst;
};
auto x1{std::memory_order::release};
ut::expect(simple_enum::enum_name(x1) == "release");
// Or just use with unbounded enums as long upper bound doesn't exceeds default_unbounded_upper_range
ut::expect(simple_enum::enum_name(any_unbounded_enum::value) == "value");
// default_unbounded_upper_range can be declared by users before inclusion of simple_enum.hpp
namespace simple_enum
{
#define SIMPLE_ENUM_CUSTOM_UNBOUNDED_RANGE
inline constexpr auto default_unbounded_upper_range = 10;
}// ranges views compatible enum_view for bounded enumerations
#includeenum weak_typed_e : uint8_t { v1, v2, v3 };
template<>
struct simple_enum::info
{
static constexpr auto first = weak_typed_e::v1;
static constexpr auto last = weak_typed_e::v3;
};
constexpr auto view = enum_view{weak_typed_e::v1, weak_typed_e::v1}
| views::transform(enum_name);
static constexpr array expected{"v1"sv};
expect(ranges::equal(view, expected));
constexpr auto view = enum_view{}
| views::transform(enum_name);
static constexpr array expected{"v1"sv, "v2"sv, "v3"sv};
expect(ranges::equal(view, expected));
// enum_cast function object for enabling the conversion from std::string_view back to the corresponding enumeration type
#include
enum struct lorem_ipsum { eu, occaecat, dolore, excepteur, mollit, adipiscing, sunt, ut, aliqua, in_case_of_error };
std::array some_data{
"excepteur", "aliqua", "occaecat", "eu", "sunt", "__SNEAKY BUG__", "adipiscing", "ut", "mollit", "dolore"};
auto view_over_lorem_ipsum2 = some_data
| std::views::transform(simple_enum::enum_cast);
for ( auto data : view_over_lorem_ipsum2 )
if(data.has_value())
std::cout << " " << enum_name(*data) << '\n';
else
std::cout << "error could happen" << enum_name(data.error()) << '\n';
```
## Performance
How v0.2.0 compares with Instantiation time:
simple enum for bounded enums to magic_enum::enum_name v0.9.5 and reflect::enum_name main/02.02.2024
clang 17 -ftime-trace on AMD Ryzen 9 5900X Linux desktop 6.6.11-gentoo-dist
enum
framework
enumerations
instantiation time
*code gen
total time
lorem_ipsum_long
simple_enum
104
12.235 ms
12.235 ms
magic_enum
199.867 ms
199.867 ms
reflect
19.282 ms
36.470 ms
55.752 ms
E
simple_enum
15
2.607 ms
2.607 ms
magic_enum
86.089 ms
86.089 ms
reflect
19.091 ms
27.475 ms
46.566 ms
lorem_ipsum_short
simple_enum
40
5.286 ms
5.286 ms
magic_enum
178.864 ms
178.864 ms
reflect
20.253 ms
41.024 ms
61.277 ms
strong_untyped
simple_enum
3
0.830 ms
0.830 ms
magic_enum
151.590 ms
151.590 ms
reflect
22.732 ms
46.484 ms
69.216 ms
*reflect is not fully comparable as part of calculations are moved to runtime and have to be paid at each enum_name call, so in table included is code generation time which is not present for simple and magic.
screen for simple_enum is from ver 0.0.1 , very early so timing is now much better as in table.

