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*/)
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</*enum_name*/, /*field_count*/ > values = {
static constexpr const std::array<enum_type, size> values = {
/*enum values*/
};
static constexpr const std::array<std::string_view, /*field_count*/> names = {
/*enum names*/
static constexpr const std::array<std::string_view, size> 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::string_view to_string_or_empty(/*enum_name*/ e) noexcept;
static std::string_view to_string_or_throw(/*enum_name*/ e);
static constexpr std::optional<std::string_view> 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</*enum_name*/> from_string(std::string_view name) noexcept;
static constexpr /*enum_name*/ from_string_or_default(std::string_view name, /*enum_name*/ def) noexcept;
static /*enum_name*/ from_string_or_throw(std::string_view name);
static constexpr std::optional<enum_type> 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<std::size_t> to_index(/*enum_name*/ e) noexcept;
static constexpr std::size_t to_index_or_invalid(/*enum_name*/ e) noexcept;
static std::size_t to_index_or_throw(/*enum_name*/ e);
static constexpr std::optional<std::size_t> 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</*enum_name*/> from_index(std::size_t index) noexcept;
static constexpr /*enum_name*/ from_index_or_default(std::size_t index, /*enum_name*/ def) noexcept;
static /*enum_name*/ from_index_or_throw(std::size_t index);
static constexpr std::optional<enum_type> 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);
};
```

View File

@@ -248,10 +248,11 @@ namespace enum_hpp::detail
ENUM_HPP_GENERATE_FIELDS(Fields)\
};\
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 const std::array<Enum, size> values = {\
static constexpr const std::array<enum_type, size> values = {\
{ ENUM_HPP_GENERATE_VALUES(Enum, Fields) }\
};\
\
@@ -259,30 +260,30 @@ namespace enum_hpp::detail
{ ENUM_HPP_GENERATE_NAMES(Fields) }\
};\
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);\
}\
\
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 ) {\
ENUM_HPP_GENERATE_VALUE_TO_NAME_CASES(Enum, Fields)\
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) ) {\
return *s;\
}\
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) ) {\
return *s;\
}\
::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) {\
if ( name == names[i] ) {\
return values[i];\
@@ -290,52 +291,52 @@ namespace enum_hpp::detail
}\
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) ) {\
return *e;\
}\
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) ) {\
return *e;\
}\
::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 ) {\
ENUM_HPP_GENERATE_VALUE_TO_INDEX_CASES(Enum, Fields)\
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) ) {\
return *i;\
}\
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) ) {\
return *i;\
}\
::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 ) {\
return values[index];\
}\
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) ) {\
return *e;\
}\
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) ) {\
return *e;\
}\

View File

@@ -22,8 +22,35 @@ namespace
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") {
SUBCASE("traits_using") {
SUBCASE("traits using") {
// size
static_assert(color_traits::size == 4);
@@ -47,16 +74,24 @@ TEST_CASE("examples") {
static_assert(color_traits::from_index(42) == std::nullopt);
// names
for ( auto n : color_traits::names ) {
for ( std::string_view n : color_traits::names ) {
std::cout << n << ",";
} // stdout: red,green,blue,
}
SUBCASE("generic_context") {
SUBCASE("generic context") {
using color = some_namespace::color;
// to string
static_assert(enum_hpp::to_string(color::red) == "red");
// from string
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>,
unsigned>);
STATIC_CHECK(std::is_same_v<
sn::color_traits::enum_type,
sn::color>);
STATIC_CHECK(std::is_same_v<
sn::color_traits::underlying_type,
enum_hpp::underlying_type<sn::color>>);