Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/BlackMATov/enum.hpp
C++17 compile-time enum reflection library
https://github.com/BlackMATov/enum.hpp
c-plus-plus c-plus-plus-17 cplusplus-17 cpp cpp17 enum enum-to-string header-only no-dependencies reflection string-to-enum
Last synced: 3 months ago
JSON representation
C++17 compile-time enum reflection library
- Host: GitHub
- URL: https://github.com/BlackMATov/enum.hpp
- Owner: BlackMATov
- License: mit
- Created: 2019-11-20T13:05:47.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2023-01-05T03:42:57.000Z (almost 2 years ago)
- Last Synced: 2024-05-02T16:10:14.315Z (6 months ago)
- Topics: c-plus-plus, c-plus-plus-17, cplusplus-17, cpp, cpp17, enum, enum-to-string, header-only, no-dependencies, reflection, string-to-enum
- Language: C++
- Homepage: https://blackmatov.github.io/enum.hpp
- Size: 379 KB
- Stars: 43
- Watchers: 5
- Forks: 6
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
- AwesomeCppGameDev - enum.hpp - time enum reflection library (C++)
README
# enum.hpp
> C++17 compile-time enum reflection library
[![linux][badge.linux]][linux]
[![darwin][badge.darwin]][darwin]
[![windows][badge.windows]][windows]
[![language][badge.language]][language]
[![license][badge.license]][license][badge.darwin]: https://img.shields.io/github/actions/workflow/status/BlackMATov/enum.hpp/.github/workflows/darwin.yml?label=Xcode&logo=xcode
[badge.linux]: https://img.shields.io/github/actions/workflow/status/BlackMATov/enum.hpp/.github/workflows/linux.yml?label=GCC%2FClang&logo=linux
[badge.windows]: https://img.shields.io/github/actions/workflow/status/BlackMATov/enum.hpp/.github/workflows/windows.yml?label=Visual%20Studio&logo=visual-studio
[badge.language]: https://img.shields.io/badge/language-C%2B%2B17-yellow
[badge.license]: https://img.shields.io/badge/license-MIT-blue[darwin]: https://github.com/BlackMATov/enum.hpp/actions?query=workflow%3Adarwin
[linux]: https://github.com/BlackMATov/enum.hpp/actions?query=workflow%3Alinux
[windows]: https://github.com/BlackMATov/enum.hpp/actions?query=workflow%3Awindows
[language]: https://en.wikipedia.org/wiki/C%2B%2B17
[license]: https://en.wikipedia.org/wiki/MIT_License[enum]: https://github.com/BlackMATov/enum.hpp
---
## Content
- [Requirements](#Requirements)
- [Installation](#Installation)
- [Examples](#Examples)
- [API](#API)
- [Alternatives](#Alternatives)
- [License](#License-(MIT))---
## Requirements
- [clang](https://clang.llvm.org/) **>= 7**
- [gcc](https://www.gnu.org/software/gcc/) **>= 7**
- [msvc](https://visualstudio.microsoft.com/) **>= 2019**
- [xcode](https://developer.apple.com/xcode/) **>= 10.3**## Installation
[enum.hpp][enum] is a header-only library. All you need to do is copy the headers files from `headers` directory into your project and include them:
```cpp
#include "enum.hpp/enum.hpp"
```Also, you can add the root repository directory to your [cmake](https://cmake.org) project:
```cmake
add_subdirectory(external/enum.hpp)
target_link_libraries(your_project_target PUBLIC enum.hpp)
```## Examples
- `enum.hpp`
- [Enum declarations](#Enum-declarations)
- [Traits using](#Traits-using)
- [Generic context](#Generic-context)
- [Adapting external enums](#Adapting-external-enums)
- `enum_bitflags.hpp`
- [Enum bitflags using](#Enum-bitflags-using)
- [Additional bitflags functions](#Additional-bitflags-functions)### Enum declarations
```cpp
// declaration of unscoped enumeration `debug_level` with traitsENUM_HPP_DECL(debug_level, int,
(level_info)
(level_warning)
(level_error))/* equivalent to:
enum debug_level : int {
level_info,
level_warning,
level_error,
};struct debug_level_traits {
...
};*/
``````cpp
// declaration of scoped enumeration `color` with traitsENUM_HPP_CLASS_DECL(color, unsigned,
(red = 1 << 0)
(green = 1 << 1)
(blue = 1 << 2)
(white = red | green | blue))/* equivalent to:
enum class color : unsigned {
red = 1 << 0,
green = 1 << 1,
blue = 1 << 2,
white = red | green | blue,
};struct color_traits {
...
};*/
```### Traits using
```cpp
namespace
{
ENUM_HPP_CLASS_DECL(color, unsigned,
(red = 0xFF0000)
(green = 0x00FF00)
(blue = 0x0000FF)
(white = red | green | blue))
}int main() {
// size
static_assert(color_traits::size == 4);// to_underlying
static_assert(color_traits::to_underlying(color::white) == 0xFFFFFF);// to_string
static_assert(color_traits::to_string(color::red) == "red");
static_assert(color_traits::to_string(color(42)) == std::nullopt);// from_string
static_assert(color_traits::from_string("green") == color::green);
static_assert(color_traits::from_string("error") == std::nullopt);// to_index
static_assert(color_traits::to_index(color::blue) == 2);
static_assert(color_traits::to_index(color(42)) == std::nullopt);// from_index
static_assert(color_traits::from_index(2) == color::blue);
static_assert(color_traits::from_index(42) == std::nullopt);// names
for ( std::string_view n : color_traits::names ) {
std::cout << n << ",";
} // stdout: red,green,blue,return 0;
}
```### Generic context
```cpp
namespace some_namespace
{
ENUM_HPP_CLASS_DECL(color, unsigned,
(red = 0xFF0000)
(green = 0x00FF00)
(blue = 0x0000FF)
(white = red | green | blue))// register traits in enum namespace to generic access
ENUM_HPP_REGISTER_TRAITS(color)
}int main() {
using color = some_namespace::color;// to string
static_assert(enum_hpp::to_string(color::red) == "red");// from string
static_assert(enum_hpp::from_string("red") == color::red);return 0;
}
```### Adapting external enums
```cpp
namespace external_ns
{
enum class external_enum : unsigned short {
a = 10,
b,
c = a + b
};// should be in the same namespace
ENUM_HPP_TRAITS_DECL(external_enum,
(a)
(b)
(c))ENUM_HPP_REGISTER_TRAITS(external_enum)
}int main() {
using ee = external_ns::external_enum;
static_assert(enum_hpp::to_string(ee::a) == "a");
static_assert(enum_hpp::from_string("c") == ee::c);
return 0;
}
```### Enum bitflags using
```cpp
#includenamespace
{
enum class perms : unsigned {
execute = 1 << 0,
write = 1 << 1,
read = 1 << 2,
};// declares operators for perms enum (~, |, &, ^)
ENUM_HPP_OPERATORS_DECL(perms)
}int main() {
namespace bf = enum_hpp::bitflags;// every enum operator returns bitflags value
bf::bitflags flags = perms::read | perms::write;// the bitflags class has some member functions for working with bit flags
if ( flags.has(perms::write) ) {
flags.clear(perms::write);
}// you can passing other the same type bitflags to these functions
flags.set(perms::write | perms::execute);// or using bit flags with the usual bit operations but type safe
if ( flags & perms::execute ) {
flags &= ~perms::execute; // flags.toggle(perms::execute);
}// or compare them, why not?
if ( flags == (perms::read | perms::write) ) {
return 0;
}return 1;
}
```### Additional bitflags functions
```cpp
#includenamespace
{
enum class perms : unsigned {
execute = 1 << 0,
write = 1 << 1,
read = 1 << 2,
};// declares operators for perms enum (~, |, &, ^)
ENUM_HPP_OPERATORS_DECL(perms)
}int main() {
namespace bf = enum_hpp::bitflags;bf::bitflags flags = perms::read | perms::write;
// bitflags namespace has many free functions
// that can accept both enumerations and bit flagsif ( bf::any_of(flags, perms::write | perms::execute) ) {
// it's writable or executable
}if ( bf::any_except(flags, perms::write | perms::execute) ) {
// and something else :-)
}
}
```## API
- `enum.hpp`
- [Enum traits](#Enum-traits)
- [Enum generic functions](#Enum-generic-functions)
- `enum_bitflags.hpp`
- [Enum bitflags](#Enum-bitflags)
- [Enum operators](#Enum-operators)
- [Enum bitflags operators](#Enum-bitflags-operators)
- [Enum bitflags functions](#Enum-bitflags-functions)### Enum traits
```cpp
// declares unscoped enumeration
ENUM_HPP_DECL(
/*enum_name*/,
/*underlying_type*/,
/*fields*/)// declares scoped enumeration
ENUM_HPP_CLASS_DECL(
/*enum_name*/,
/*underlying_type*/,
/*fields*/)// declares only traits for external enumerations
ENUM_HPP_TRAITS_DECL(
/*enum_name*/,
/*fields*/)// declared enumeration traits
struct /*enum_name*/_traits {
using enum_type = /*enum_name*/;
using underlying_type = /*underlying_type*/;
static constexpr std::size_t size = /*field_count*/;static constexpr const std::array values = {
/*enum values*/
};static constexpr const std::array names = {
/*enum value names*/
};static constexpr underlying_type to_underlying(enum_type e) noexcept;
static constexpr std::optional to_string(enum_type e) noexcept;
static constexpr std::string_view to_string_or_empty(enum_type e) noexcept;
static std::string_view to_string_or_throw(enum_type e);static constexpr std::optional from_string(std::string_view name) noexcept;
static constexpr enum_type from_string_or_default(std::string_view name, enum_type def) noexcept;
static enum_type from_string_or_throw(std::string_view name);static constexpr std::optional to_index(enum_type e) noexcept;
static constexpr std::size_t to_index_or_invalid(enum_type e) noexcept;
static std::size_t to_index_or_throw(enum_type e);static constexpr std::optional from_index(std::size_t index) noexcept;
static constexpr enum_type from_index_or_default(std::size_t index, enum_type def) noexcept;
static enum_type from_index_or_throw(std::size_t index);
};
```### Enum generic functions
```cpp
// should be in enum namespace
ENUM_HPP_REGISTER_TRAITS(/*declared_enum_name*/)namespace enum_hpp
{
template < typename Enum >
using traits_t = typename traits::type;template < typename Enum >
using underlying_type = typename traits_t::underlying_type;template < typename Enum >
constexpr std::size_t size() noexcept;template < typename Enum >
constexpr const std::array()>& values() noexcept;template < typename Enum >
constexpr const std::array()>& names() noexcept;template < typename Enum >
constexpr typename traits_t::underlying_type to_underlying(Enum e) noexcept;template < typename Enum >
constexpr std::optional to_string(Enum e) noexcept;template < typename Enum >
constexpr std::string_view to_string_or_empty(Enum e) noexcept;template < typename Enum >
std::string_view to_string_or_throw(Enum e);template < typename Enum >
constexpr std::optional from_string(std::string_view name) noexcept;template < typename Enum >
constexpr Enum from_string_or_default(std::string_view name, Enum def) noexcept;template < typename Enum >
Enum from_string_or_throw(std::string_view name);template < typename Enum >
constexpr std::optional to_index(Enum e) noexcept;template < typename Enum >
constexpr std::size_t to_index_or_invalid(Enum e) noexcept;template < typename Enum >
std::size_t to_index_or_throw(Enum e);template < typename Enum >
constexpr std::optional from_index(std::size_t index) noexcept;template < typename Enum >
constexpr Enum from_index_or_default(std::size_t index, Enum def) noexcept;template < typename Enum >
Enum from_index_or_throw(std::size_t index);
}
```### Enum bitflags
```cpp
namespace enum_hpp::bitflags
{
template < typename Enum >
class bitflags final {
public:
using enum_type = Enum;
using underlying_type = std::underlying_type_t;bitflags() = default;
bitflags(const bitflags&) = default;
bitflags& operator=(const bitflags&) = default;constexpr bitflags(enum_type flags);
constexpr explicit bitflags(underlying_type flags);constexpr void swap(bitflags& other) noexcept;
constexpr explicit operator bool() const noexcept;constexpr underlying_type as_raw() const noexcept;
constexpr enum_type as_enum() const noexcept;constexpr bool has(bitflags flags) const noexcept;
constexpr bitflags& set(bitflags flags) noexcept;
constexpr bitflags& toggle(bitflags flags) noexcept;
constexpr bitflags& clear(bitflags flags) noexcept;
};template < typename Enum >
constexpr void swap(bitflags& l, bitflags& r) noexcept;
}namespace std
{
template < typename Enum >
struct hash> {
size_t operator()(enum_hpp::bitflags::bitflags bf) const noexcept;
};
}
```### Enum operators
```cpp
// declares enumeration operators
ENUM_HPP_OPERATORS_DECL(/*enum_name*/)// declared enumeration operators
constexpr bitflags operator ~ (/*enum_name*/ l) noexcept;
constexpr bitflags operator | (/*enum_name*/ l, /*enum_name*/ r) noexcept;
constexpr bitflags operator & (/*enum_name*/ l, /*enum_name*/ r) noexcept;
constexpr bitflags operator ^ (/*enum_name*/ l, /*enum_name*/ r) noexcept;
```### Enum bitflags operators
```cpp
namespace enum_hpp::bitflags
{
template < typename Enum >
constexpr bool operator < (Enum l, bitflags r) noexcept;template < typename Enum >
constexpr bool operator < (bitflags l, Enum r) noexcept;template < typename Enum >
constexpr bool operator < (std::underlying_type_t l, bitflags r) noexcept;template < typename Enum >
constexpr bool operator < (bitflags l, std::underlying_type_t r) noexcept;template < typename Enum >
constexpr bool operator < (bitflags l, bitflags r) noexcept;// and also for other comparison operators (<, >, <=, >=, ==, !=)
}namespace enum_hpp::bitflags
{
template < typename Enum >
constexpr bitflags operator ~ (bitflags l) noexcept;template < typename Enum >
constexpr bitflags operator | (Enum l, bitflags r) noexcept;template < typename Enum >
constexpr bitflags operator | (bitflags l, Enum r) noexcept;template < typename Enum >
constexpr bitflags operator | (bitflags l, bitflags r) noexcept;template < typename Enum >
constexpr bitflags& operator |= (bitflags& l, Enum r) noexcept;template < typename Enum >
constexpr bitflags& operator |= (bitflags& l, bitflags r) noexcept;// and also for other bitwise logic operators (|, |=, &, &=, ^, ^=)
}
```### Enum bitflags functions
```cpp
namespace enum_hpp::bitflags
{
// anytemplate < enum Enum >
constexpr bool any(Enum flags) noexcept;template < typename Enum >
constexpr bool any(bitflags flags) noexcept;// none
template < enum Enum >
constexpr bool none(Enum flags) noexcept;template < typename Enum >
constexpr bool none(bitflags flags) noexcept;// all_of
template < enum Enum >
constexpr bool all_of(Enum flags, Enum mask) noexcept;template < typename Enum >
constexpr bool all_of(Enum flags, bitflags mask) noexcept;template < typename Enum >
constexpr bool all_of(bitflags flags, Enum mask) noexcept;template < typename Enum >
constexpr bool all_of(bitflags flags, bitflags mask) noexcept;// any_of
template < enum Enum >
constexpr bool any_of(Enum flags, Enum mask) noexcept;template < typename Enum >
constexpr bool any_of(Enum flags, bitflags mask) noexcept;template < typename Enum >
constexpr bool any_of(bitflags flags, Enum mask) noexcept;template < typename Enum >
constexpr bool any_of(bitflags flags, bitflags mask) noexcept;// none_of
template < enum Enum >
constexpr bool none_of(Enum flags, Enum mask) noexcept;template < typename Enum >
constexpr bool none_of(Enum flags, bitflags mask) noexcept;template < typename Enum >
constexpr bool none_of(bitflags flags, Enum mask) noexcept;template < typename Enum >
constexpr bool none_of(bitflags flags, bitflags mask) noexcept;// any_except
template < enum Enum >
constexpr bool any_except(Enum flags, Enum mask) noexcept;template < typename Enum >
constexpr bool any_except(Enum flags, bitflags mask) noexcept;template < typename Enum >
constexpr bool any_except(bitflags flags, Enum mask) noexcept;template < typename Enum >
constexpr bool any_except(bitflags flags, bitflags mask) noexcept;// none_except
template < enum Enum >
constexpr bool none_except(Enum flags, Enum mask) noexcept;template < typename Enum >
constexpr bool none_except(Enum flags, bitflags mask) noexcept;template < typename Enum >
constexpr bool none_except(bitflags flags, Enum mask) noexcept;template < typename Enum >
constexpr bool none_except(bitflags flags, bitflags mask) noexcept;
}
```## Alternatives
[Better Enums](https://github.com/aantron/better-enums)
- Low variadic macros limit (64)
- Replaces C++ enum semantics to custom class[wise_enum](https://github.com/quicknir/wise_enum)
- Limited by variadic macros ([msvs: 127](https://docs.microsoft.com/en-us/cpp/cpp/compiler-limits?view=vs-2019))
[Magic Enum](https://github.com/Neargye/magic_enum)
- Amazing but requires at least GCC 9.0
## [License (MIT)](./LICENSE.md)