- Notifications
You must be signed in to change notification settings - Fork6
C++17 compile-time enum reflection library
License
NotificationsYou must be signed in to change notification settings
BlackMATov/enum.hpp
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
C++17 compile-time enum reflection library
enum.hpp is a header-only library. All you need to do is copy the headers files fromheaders
directory into your project and include them:
#include"enum.hpp/enum.hpp"
Also, you can add the root repository directory to yourcmake project:
add_subdirectory(external/enum.hpp)target_link_libraries(your_project_targetPUBLIC enum.hpp)
enum.hpp
enum_bitflags.hpp
// 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 { ...};*/
// 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 { ...};*/
namespace{ENUM_HPP_CLASS_DECL(color,unsigned, (red =0xFF0000) (green =0x00FF00) (blue =0x0000FF) (white = red | green | blue))}intmain() {// sizestatic_assert(color_traits::size ==4);// to_underlyingstatic_assert(color_traits::to_underlying(color::white) ==0xFFFFFF);// to_stringstatic_assert(color_traits::to_string(color::red) =="red");static_assert(color_traits::to_string(color(42)) == std::nullopt);// from_stringstatic_assert(color_traits::from_string("green") == color::green);static_assert(color_traits::from_string("error") == std::nullopt);// to_indexstatic_assert(color_traits::to_index(color::blue) ==2);static_assert(color_traits::to_index(color(42)) == std::nullopt);// from_indexstatic_assert(color_traits::from_index(2) == color::blue);static_assert(color_traits::from_index(42) == std::nullopt);// namesfor ( std::string_view n : color_traits::names ) { std::cout << n <<","; }// stdout: red,green,blue,return0;}
namespacesome_namespace{ENUM_HPP_CLASS_DECL(color,unsigned, (red =0xFF0000) (green =0x00FF00) (blue =0x0000FF) (white = red | green | blue))// register traits in enum namespace to generic accessENUM_HPP_REGISTER_TRAITS(color)}intmain() {using color = some_namespace::color;// to stringstatic_assert(enum_hpp::to_string(color::red) =="red");// from stringstatic_assert(enum_hpp::from_string<color>("red") == color::red);return0;}
namespaceexternal_ns{enumclassexternal_enum :unsignedshort { a =10, b, c = a + b };// should be in the same namespaceENUM_HPP_TRAITS_DECL(external_enum, (a) (b) (c))ENUM_HPP_REGISTER_TRAITS(external_enum)}intmain() {using ee = external_ns::external_enum;static_assert(enum_hpp::to_string(ee::a) =="a");static_assert(enum_hpp::from_string<ee>("c") == ee::c);return0;}
#include<enum.hpp/enum_bitflags.hpp>namespace{enumclassperms :unsigned { execute =1 <<0, write =1 <<1, read =1 <<2, };// declares operators for perms enum (~, |, &, ^)ENUM_HPP_OPERATORS_DECL(perms)}intmain() {namespacebf= enum_hpp::bitflags;// every enum operator returns bitflags<enum> value bf::bitflags flags = perms::read | perms::write;// the bitflags class has some member functions for working with bit flagsif ( 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 safeif ( flags & perms::execute ) { flags &= ~perms::execute;// flags.toggle(perms::execute); }// or compare them, why not?if ( flags == (perms::read | perms::write) ) {return0; }return1;}
#include<enum.hpp/enum_bitflags.hpp>namespace{enumclassperms :unsigned { execute =1 <<0, write =1 <<1, read =1 <<2, };// declares operators for perms enum (~, |, &, ^)ENUM_HPP_OPERATORS_DECL(perms)}intmain() {namespacebf= enum_hpp::bitflags; bf::bitflags<perms> 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 :-) }}
enum.hpp
enum_bitflags.hpp
// declares unscoped enumerationENUM_HPP_DECL(/*enum_name*/,/*underlying_type*/,/*fields*/)// declares scoped enumerationENUM_HPP_CLASS_DECL(/*enum_name*/,/*underlying_type*/,/*fields*/)// declares only traits for external enumerationsENUM_HPP_TRAITS_DECL(/*enum_name*/,/*fields*/)// declared enumeration traitsstruct/*enum_name*/_traits {using enum_type =/*enum_name*/;using underlying_type =/*underlying_type*/;staticconstexpr std::size_t size =/*field_count*/;staticconstexprconst std::array<enum_type, size> values = {/*enum values*/ };staticconstexprconst std::array<std::string_view, size> names = {/*enum value names*/ };staticconstexpr underlying_typeto_underlying(enum_type e)noexcept;staticconstexpr std::optional<std::string_view>to_string(enum_type e)noexcept;staticconstexpr std::string_viewto_string_or_empty(enum_type e)noexcept;static std::string_viewto_string_or_throw(enum_type e);staticconstexpr std::optional<enum_type>from_string(std::string_view name)noexcept;staticconstexpr enum_typefrom_string_or_default(std::string_view name, enum_type def)noexcept;static enum_typefrom_string_or_throw(std::string_view name);staticconstexpr std::optional<std::size_t>to_index(enum_type e)noexcept;staticconstexpr std::size_tto_index_or_invalid(enum_type e)noexcept;static std::size_tto_index_or_throw(enum_type e);staticconstexpr std::optional<enum_type>from_index(std::size_tindex)noexcept;staticconstexpr enum_typefrom_index_or_default(std::size_tindex, enum_type def)noexcept;static enum_typefrom_index_or_throw(std::size_tindex);};
// should be in enum namespaceENUM_HPP_REGISTER_TRAITS(/*declared_enum_name*/)namespace enum_hpp{template<typename Enum >usingtraits_t =typename traits<Enum>::type;template<typename Enum >using underlying_type =typenametraits_t<Enum>::underlying_type;template<typename Enum >constexpr std::size_tsize()noexcept;template<typename Enum >constexprconst std::array<Enum, size<Enum>()>&values()noexcept;template<typename Enum >constexprconst std::array<std::string_view, size<Enum>()>&names()noexcept;template<typename Enum >constexprtypenametraits_t<Enum>::underlying_typeto_underlying(Enum e)noexcept;template<typename Enum >constexpr std::optional<std::string_view>to_string(Enum e)noexcept;template<typename Enum >constexpr std::string_viewto_string_or_empty(Enum e)noexcept;template<typename Enum > std::string_viewto_string_or_throw(Enum e);template<typename Enum >constexpr std::optional<Enum>from_string(std::string_view name)noexcept;template<typename Enum >constexpr Enumfrom_string_or_default(std::string_view name, Enum def)noexcept;template<typename Enum > Enumfrom_string_or_throw(std::string_view name);template<typename Enum >constexpr std::optional<std::size_t>to_index(Enum e)noexcept;template<typename Enum >constexpr std::size_tto_index_or_invalid(Enum e)noexcept;template<typename Enum > std::size_tto_index_or_throw(Enum e);template<typename Enum >constexpr std::optional<Enum>from_index(std::size_tindex)noexcept;template<typename Enum >constexpr Enumfrom_index_or_default(std::size_tindex, Enum def)noexcept;template<typename Enum > Enumfrom_index_or_throw(std::size_tindex);}
namespaceenum_hpp::bitflags{template<typename Enum >classbitflagsfinal {public:using enum_type = Enum;using underlying_type = std::underlying_type_t<Enum>;bitflags() =default;bitflags(const bitflags&) =default; bitflags&operator=(const bitflags&) =default;constexprbitflags(enum_type flags);constexprexplicitbitflags(underlying_type flags);constexprvoidswap(bitflags& other)noexcept;constexprexplicitoperatorbool()constnoexcept;constexpr underlying_typeas_raw()constnoexcept;constexpr enum_typeas_enum()constnoexcept;constexprboolhas(bitflags flags)constnoexcept;constexpr bitflags&set(bitflags flags)noexcept;constexpr bitflags&toggle(bitflags flags)noexcept;constexpr bitflags&clear(bitflags flags)noexcept; };template<typename Enum >constexprvoidswap(bitflags<Enum>& l, bitflags<Enum>& r)noexcept;}namespacestd{template<typename Enum >structhash<enum_hpp::bitflags::bitflags<Enum>> {size_toperator()(enum_hpp::bitflags::bitflags<Enum> bf)constnoexcept; };}
// declares enumeration operatorsENUM_HPP_OPERATORS_DECL(/*enum_name*/)// declared enumeration operatorsconstexpr bitflags<Enum> operator ~ (/*enum_name*/ l)noexcept;constexpr bitflags<Enum>operator | (/*enum_name*/ l,/*enum_name*/ r)noexcept;constexpr bitflags<Enum>operator & (/*enum_name*/ l,/*enum_name*/ r)noexcept;constexpr bitflags<Enum>operator ^ (/*enum_name*/ l,/*enum_name*/ r)noexcept;
namespaceenum_hpp::bitflags{template<typename Enum >constexprbooloperator < (Enum l, bitflags<Enum> r)noexcept;template<typename Enum >constexprbooloperator < (bitflags<Enum> l, Enum r)noexcept;template<typename Enum >constexprbooloperator < (std::underlying_type_t<Enum> l, bitflags<Enum> r)noexcept;template<typename Enum >constexprbooloperator < (bitflags<Enum> l, std::underlying_type_t<Enum> r)noexcept;template<typename Enum >constexprbooloperator < (bitflags<Enum> l, bitflags<Enum> r)noexcept;// and also for other comparison operators (<, >, <=, >=, ==, !=)}namespaceenum_hpp::bitflags{template<typename Enum >constexpr bitflags<Enum>operator ~ (bitflags<Enum> l)noexcept;template<typename Enum >constexpr bitflags<Enum>operator | (Enum l, bitflags<Enum> r)noexcept;template<typename Enum >constexpr bitflags<Enum>operator | (bitflags<Enum> l, Enum r)noexcept;template<typename Enum >constexpr bitflags<Enum>operator | (bitflags<Enum> l, bitflags<Enum> r)noexcept;template<typename Enum >constexpr bitflags<Enum>&operator |= (bitflags<Enum>& l, Enum r)noexcept;template<typename Enum >constexpr bitflags<Enum>&operator |= (bitflags<Enum>& l, bitflags<Enum> r)noexcept;// and also for other bitwise logic operators (|, |=, &, &=, ^, ^=)}
namespaceenum_hpp::bitflags{// anytemplate<enum Enum >constexprboolany(Enum flags)noexcept;template<typename Enum >constexprboolany(bitflags<Enum> flags)noexcept;// nonetemplate<enum Enum >constexprboolnone(Enum flags)noexcept;template<typename Enum >constexprboolnone(bitflags<Enum> flags)noexcept;// all_oftemplate<enum Enum >constexprboolall_of(Enum flags, Enum mask)noexcept;template<typename Enum >constexprboolall_of(Enum flags, bitflags<Enum> mask)noexcept;template<typename Enum >constexprboolall_of(bitflags<Enum> flags, Enum mask)noexcept;template<typename Enum >constexprboolall_of(bitflags<Enum> flags, bitflags<Enum> mask)noexcept;// any_oftemplate<enum Enum >constexprboolany_of(Enum flags, Enum mask)noexcept;template<typename Enum >constexprboolany_of(Enum flags, bitflags<Enum> mask)noexcept;template<typename Enum >constexprboolany_of(bitflags<Enum> flags, Enum mask)noexcept;template<typename Enum >constexprboolany_of(bitflags<Enum> flags, bitflags<Enum> mask)noexcept;// none_oftemplate<enum Enum >constexprboolnone_of(Enum flags, Enum mask)noexcept;template<typename Enum >constexprboolnone_of(Enum flags, bitflags<Enum> mask)noexcept;template<typename Enum >constexprboolnone_of(bitflags<Enum> flags, Enum mask)noexcept;template<typename Enum >constexprboolnone_of(bitflags<Enum> flags, bitflags<Enum> mask)noexcept;// any_excepttemplate<enum Enum >constexprboolany_except(Enum flags, Enum mask)noexcept;template<typename Enum >constexprboolany_except(Enum flags, bitflags<Enum> mask)noexcept;template<typename Enum >constexprboolany_except(bitflags<Enum> flags, Enum mask)noexcept;template<typename Enum >constexprboolany_except(bitflags<Enum> flags, bitflags<Enum> mask)noexcept;// none_excepttemplate<enum Enum >constexprboolnone_except(Enum flags, Enum mask)noexcept;template<typename Enum >constexprboolnone_except(Enum flags, bitflags<Enum> mask)noexcept;template<typename Enum >constexprboolnone_except(bitflags<Enum> flags, Enum mask)noexcept;template<typename Enum >constexprboolnone_except(bitflags<Enum> flags, bitflags<Enum> mask)noexcept;}
- Low variadic macros limit (64)
- Replaces C++ enum semantics to custom class
- Limited by variadic macros (msvs: 127)
- Amazing but requires at least GCC 9.0
About
C++17 compile-time enum reflection library