add enum_type to traits

This commit is contained in:
BlackMATov
2020-12-18 23:50:04 +07:00
parent 55055a23dc
commit fce42579f0
4 changed files with 75 additions and 34 deletions

View File

@@ -213,34 +213,35 @@ ENUM_HPP_TRAITS_DECL(
/*fields*/) /*fields*/)
struct /*enum_name*/_traits { struct /*enum_name*/_traits {
using enum_type = /*enum_name*/;
using underlying_type = /*underlying_type*/; using underlying_type = /*underlying_type*/;
static constexpr std::size_t size = /*field_count*/; static constexpr std::size_t size = /*field_count*/;
static constexpr const std::array</*enum_name*/, /*field_count*/ > values = { static constexpr const std::array<enum_type, size> values = {
/*enum values*/ /*enum values*/
}; };
static constexpr const std::array<std::string_view, /*field_count*/> names = { static constexpr const std::array<std::string_view, size> names = {
/*enum names*/ /*enum value names*/
}; };
static constexpr /*underlying_type*/ to_underlying(/*enum_name*/ e) noexcept; static constexpr underlying_type to_underlying(enum_type e) noexcept;
static constexpr std::optional<std::string_view> to_string(/*enum_name*/ e) noexcept; static constexpr std::optional<std::string_view> to_string(enum_type e) noexcept;
static constexpr std::string_view to_string_or_empty(/*enum_name*/ e) noexcept; static constexpr std::string_view to_string_or_empty(enum_type e) noexcept;
static std::string_view to_string_or_throw(/*enum_name*/ e); static std::string_view to_string_or_throw(enum_type e);
static constexpr std::optional</*enum_name*/> from_string(std::string_view name) noexcept; static constexpr std::optional<enum_type> from_string(std::string_view name) noexcept;
static constexpr /*enum_name*/ from_string_or_default(std::string_view name, /*enum_name*/ def) noexcept; static constexpr enum_type from_string_or_default(std::string_view name, enum_type def) noexcept;
static /*enum_name*/ from_string_or_throw(std::string_view name); static enum_type from_string_or_throw(std::string_view name);
static constexpr std::optional<std::size_t> to_index(/*enum_name*/ e) noexcept; static constexpr std::optional<std::size_t> to_index(enum_type e) noexcept;
static constexpr std::size_t to_index_or_invalid(/*enum_name*/ e) noexcept; static constexpr std::size_t to_index_or_invalid(enum_type e) noexcept;
static std::size_t to_index_or_throw(/*enum_name*/ e); static std::size_t to_index_or_throw(enum_type e);
static constexpr std::optional</*enum_name*/> from_index(std::size_t index) noexcept; static constexpr std::optional<enum_type> from_index(std::size_t index) noexcept;
static constexpr /*enum_name*/ from_index_or_default(std::size_t index, /*enum_name*/ def) noexcept; static constexpr enum_type from_index_or_default(std::size_t index, enum_type def) noexcept;
static /*enum_name*/ from_index_or_throw(std::size_t index); static enum_type from_index_or_throw(std::size_t index);
}; };
``` ```

View File

@@ -248,10 +248,11 @@ namespace enum_hpp::detail
ENUM_HPP_GENERATE_FIELDS(Fields)\ ENUM_HPP_GENERATE_FIELDS(Fields)\
};\ };\
public:\ public:\
using underlying_type = std::underlying_type_t<Enum>;\ using enum_type = Enum;\
using underlying_type = std::underlying_type_t<enum_type>;\
static constexpr std::size_t size = ENUM_HPP_PP_SEQ_SIZE(Fields);\ static constexpr std::size_t size = ENUM_HPP_PP_SEQ_SIZE(Fields);\
\ \
static constexpr const std::array<Enum, size> values = {\ static constexpr const std::array<enum_type, size> values = {\
{ ENUM_HPP_GENERATE_VALUES(Enum, Fields) }\ { ENUM_HPP_GENERATE_VALUES(Enum, Fields) }\
};\ };\
\ \
@@ -259,30 +260,30 @@ namespace enum_hpp::detail
{ ENUM_HPP_GENERATE_NAMES(Fields) }\ { ENUM_HPP_GENERATE_NAMES(Fields) }\
};\ };\
public:\ public:\
static constexpr underlying_type to_underlying(Enum e) noexcept {\ static constexpr underlying_type to_underlying(enum_type e) noexcept {\
return static_cast<underlying_type>(e);\ return static_cast<underlying_type>(e);\
}\ }\
\ \
static constexpr std::optional<std::string_view> to_string(Enum e) noexcept {\ static constexpr std::optional<std::string_view> to_string(enum_type e) noexcept {\
switch ( e ) {\ switch ( e ) {\
ENUM_HPP_GENERATE_VALUE_TO_NAME_CASES(Enum, Fields)\ ENUM_HPP_GENERATE_VALUE_TO_NAME_CASES(Enum, Fields)\
default: return std::nullopt;\ default: return std::nullopt;\
}\ }\
}\ }\
static constexpr std::string_view to_string_or_empty(Enum e) noexcept {\ static constexpr std::string_view to_string_or_empty(enum_type e) noexcept {\
if ( auto s = to_string(e) ) {\ if ( auto s = to_string(e) ) {\
return *s;\ return *s;\
}\ }\
return ::enum_hpp::empty_string;\ return ::enum_hpp::empty_string;\
}\ }\
static std::string_view to_string_or_throw(Enum e) {\ static std::string_view to_string_or_throw(enum_type e) {\
if ( auto s = to_string(e) ) {\ if ( auto s = to_string(e) ) {\
return *s;\ return *s;\
}\ }\
::enum_hpp::detail::throw_exception_with(#Enum "_traits::to_string_or_throw(): invalid argument");\ ::enum_hpp::detail::throw_exception_with(#Enum "_traits::to_string_or_throw(): invalid argument");\
}\ }\
\ \
static constexpr std::optional<Enum> from_string(std::string_view name) noexcept {\ static constexpr std::optional<enum_type> from_string(std::string_view name) noexcept {\
for ( std::size_t i = 0; i < size; ++i) {\ for ( std::size_t i = 0; i < size; ++i) {\
if ( name == names[i] ) {\ if ( name == names[i] ) {\
return values[i];\ return values[i];\
@@ -290,52 +291,52 @@ namespace enum_hpp::detail
}\ }\
return std::nullopt;\ return std::nullopt;\
}\ }\
static constexpr Enum from_string_or_default(std::string_view name, Enum def) noexcept {\ static constexpr enum_type from_string_or_default(std::string_view name, enum_type def) noexcept {\
if ( auto e = from_string(name) ) {\ if ( auto e = from_string(name) ) {\
return *e;\ return *e;\
}\ }\
return def;\ return def;\
}\ }\
static Enum from_string_or_throw(std::string_view name) {\ static enum_type from_string_or_throw(std::string_view name) {\
if ( auto e = from_string(name) ) {\ if ( auto e = from_string(name) ) {\
return *e;\ return *e;\
}\ }\
::enum_hpp::detail::throw_exception_with(#Enum "_traits::from_string_or_throw(): invalid argument");\ ::enum_hpp::detail::throw_exception_with(#Enum "_traits::from_string_or_throw(): invalid argument");\
}\ }\
\ \
static constexpr std::optional<std::size_t> to_index(Enum e) noexcept {\ static constexpr std::optional<std::size_t> to_index(enum_type e) noexcept {\
switch ( e ) {\ switch ( e ) {\
ENUM_HPP_GENERATE_VALUE_TO_INDEX_CASES(Enum, Fields)\ ENUM_HPP_GENERATE_VALUE_TO_INDEX_CASES(Enum, Fields)\
default: return std::nullopt;\ default: return std::nullopt;\
}\ }\
}\ }\
\ \
static constexpr std::size_t to_index_or_invalid(Enum e) noexcept {\ static constexpr std::size_t to_index_or_invalid(enum_type e) noexcept {\
if ( auto i = to_index(e) ) {\ if ( auto i = to_index(e) ) {\
return *i;\ return *i;\
}\ }\
return ::enum_hpp::invalid_index;\ return ::enum_hpp::invalid_index;\
}\ }\
static std::size_t to_index_or_throw(Enum e) {\ static std::size_t to_index_or_throw(enum_type e) {\
if ( auto i = to_index(e) ) {\ if ( auto i = to_index(e) ) {\
return *i;\ return *i;\
}\ }\
::enum_hpp::detail::throw_exception_with(#Enum "_traits::to_index_or_throw(): invalid argument");\ ::enum_hpp::detail::throw_exception_with(#Enum "_traits::to_index_or_throw(): invalid argument");\
}\ }\
\ \
static constexpr std::optional<Enum> from_index(std::size_t index) noexcept {\ static constexpr std::optional<enum_type> from_index(std::size_t index) noexcept {\
if ( index < size ) {\ if ( index < size ) {\
return values[index];\ return values[index];\
}\ }\
return std::nullopt;\ return std::nullopt;\
}\ }\
static constexpr Enum from_index_or_default(std::size_t index, Enum def) noexcept {\ static constexpr enum_type from_index_or_default(std::size_t index, enum_type def) noexcept {\
if ( auto e = from_index(index) ) {\ if ( auto e = from_index(index) ) {\
return *e;\ return *e;\
}\ }\
return def;\ return def;\
}\ }\
static Enum from_index_or_throw(std::size_t index) {\ static enum_type from_index_or_throw(std::size_t index) {\
if ( auto e = from_index(index) ) {\ if ( auto e = from_index(index) ) {\
return *e;\ return *e;\
}\ }\

View File

@@ -22,8 +22,35 @@ namespace
ENUM_HPP_REGISTER_TRAITS(color) ENUM_HPP_REGISTER_TRAITS(color)
} }
namespace some_namespace
{
ENUM_HPP_CLASS_DECL(color, unsigned,
(red = 0xFF0000)
(green = 0x00FF00)
(blue = 0x0000FF)
(white = red | green | blue))
ENUM_HPP_REGISTER_TRAITS(color)
}
namespace external_ns
{
enum class external_enum : unsigned short {
a = 10,
b,
c = a + b
};
ENUM_HPP_TRAITS_DECL(external_enum,
(a)
(b)
(c))
ENUM_HPP_REGISTER_TRAITS(external_enum)
}
TEST_CASE("examples") { TEST_CASE("examples") {
SUBCASE("traits_using") { SUBCASE("traits using") {
// size // size
static_assert(color_traits::size == 4); static_assert(color_traits::size == 4);
@@ -47,16 +74,24 @@ TEST_CASE("examples") {
static_assert(color_traits::from_index(42) == std::nullopt); static_assert(color_traits::from_index(42) == std::nullopt);
// names // names
for ( auto n : color_traits::names ) { for ( std::string_view n : color_traits::names ) {
std::cout << n << ","; std::cout << n << ",";
} // stdout: red,green,blue, } // stdout: red,green,blue,
} }
SUBCASE("generic_context") { SUBCASE("generic context") {
using color = some_namespace::color;
// to string // to string
static_assert(enum_hpp::to_string(color::red) == "red"); static_assert(enum_hpp::to_string(color::red) == "red");
// from string // from string
static_assert(enum_hpp::from_string<color>("red") == color::red); static_assert(enum_hpp::from_string<color>("red") == color::red);
} }
SUBCASE("external enums") {
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);
}
} }

View File

@@ -82,6 +82,10 @@ TEST_CASE("enum") {
std::underlying_type_t<sn::color>, std::underlying_type_t<sn::color>,
unsigned>); unsigned>);
STATIC_CHECK(std::is_same_v<
sn::color_traits::enum_type,
sn::color>);
STATIC_CHECK(std::is_same_v< STATIC_CHECK(std::is_same_v<
sn::color_traits::underlying_type, sn::color_traits::underlying_type,
enum_hpp::underlying_type<sn::color>>); enum_hpp::underlying_type<sn::color>>);