Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

C++17 compile-time enum reflection library

License

NotificationsYou must be signed in to change notification settings

BlackMATov/enum.hpp

Repository files navigation

C++17 compile-time enum reflection library

linuxdarwinwindowslanguagelicense


Content


Requirements

Installation

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)

Examples

Enum declarations

// 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 {    ...};*/

Traits using

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;}

Generic context

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;}

Adapting external enums

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;}

Enum bitflags using

#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;}

Additional bitflags functions

#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 :-)    }}

API

Enum traits

// 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);};

Enum generic functions

// 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);}

Enum bitflags

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;    };}

Enum operators

// 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;

Enum bitflags operators

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 (|, |=, &, &=, ^, ^=)}

Enum bitflags functions

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;}

Alternatives

Better Enums

  • Low variadic macros limit (64)
  • Replaces C++ enum semantics to custom class

wise_enum

Magic Enum

  • Amazing but requires at least GCC 9.0

[8]ページ先頭

©2009-2025 Movatter.jp