improve nameof_enum<V>()

This commit is contained in:
neargye 2019-11-14 17:16:39 +05:00
parent 1e0c019453
commit 05eb30b844
2 changed files with 15 additions and 18 deletions

View file

@ -578,7 +578,7 @@ constexpr auto n() noexcept {
# elif defined(_MSC_VER) # elif defined(_MSC_VER)
constexpr std::string_view name{__FUNCSIG__ + 63, sizeof(__FUNCSIG__) - 81 - (__FUNCSIG__[sizeof(__FUNCSIG__) - 19] == ' ' ? 1 : 0)}; constexpr std::string_view name{__FUNCSIG__ + 63, sizeof(__FUNCSIG__) - 81 - (__FUNCSIG__[sizeof(__FUNCSIG__) - 19] == ' ' ? 1 : 0)};
# endif # endif
static_assert(!name.empty(), "Type does not have a name."); static_assert(name.size() > 0, "Type does not have a name.");
return cstring<name.size()>{name}; return cstring<name.size()>{name};
#else #else
@ -604,8 +604,13 @@ template <typename E>
// Obtains simple (unqualified) string enum name of static storage enum variable. // Obtains simple (unqualified) string enum name of static storage enum variable.
// This version is much lighter on the compile times and is not restricted to the enum_range limitation. // This version is much lighter on the compile times and is not restricted to the enum_range limitation.
template <auto V> template <auto V>
[[nodiscard]] constexpr auto nameof_enum() noexcept -> detail::enable_if_enum_t<decltype(V), std::string_view> { [[nodiscard]] constexpr auto nameof_enum() noexcept {
return detail::enum_name_v<detail::remove_cvref_t<decltype(V)>, V>; using D = detail::remove_cvref_t<decltype(V)>;
static_assert(std::is_enum_v<D>, "nameof::nameof_enum requires enum type.");
constexpr auto name = detail::n<D, V>();
static_assert(name.size() > 0, "Enum value does not have a name.");
return cstring<name.size()>{name};
} }
// Obtains string name of type, reference and cv-qualifiers are ignored. // Obtains string name of type, reference and cv-qualifiers are ignored.
@ -634,7 +639,7 @@ template <typename T>
#define NAMEOF(...) []() constexpr noexcept { \ #define NAMEOF(...) []() constexpr noexcept { \
::std::void_t<decltype(__VA_ARGS__)>(); \ ::std::void_t<decltype(__VA_ARGS__)>(); \
constexpr auto name = ::nameof::detail::pretty_name(#__VA_ARGS__, true); \ constexpr auto name = ::nameof::detail::pretty_name(#__VA_ARGS__, true); \
static_assert(!name.empty(), "Expression does not have a name."); \ static_assert(name.size() > 0, "Expression does not have a name."); \
constexpr auto size = name.size(); \ constexpr auto size = name.size(); \
return ::nameof::cstring<size>{name}; }() return ::nameof::cstring<size>{name}; }()
@ -642,7 +647,7 @@ template <typename T>
#define NAMEOF_FULL(...) []() constexpr noexcept { \ #define NAMEOF_FULL(...) []() constexpr noexcept { \
::std::void_t<decltype(__VA_ARGS__)>(); \ ::std::void_t<decltype(__VA_ARGS__)>(); \
constexpr auto name = ::nameof::detail::pretty_name(#__VA_ARGS__, false); \ constexpr auto name = ::nameof::detail::pretty_name(#__VA_ARGS__, false); \
static_assert(!name.empty(), "Expression does not have a name."); \ static_assert(name.size() > 0, "Expression does not have a name."); \
constexpr auto size = name.size(); \ constexpr auto size = name.size(); \
return ::nameof::cstring<size>{name}; }() return ::nameof::cstring<size>{name}; }()
@ -650,7 +655,7 @@ template <typename T>
#define NAMEOF_RAW(...) []() constexpr noexcept { \ #define NAMEOF_RAW(...) []() constexpr noexcept { \
::std::void_t<decltype(__VA_ARGS__)>(); \ ::std::void_t<decltype(__VA_ARGS__)>(); \
constexpr auto name = ::std::string_view{#__VA_ARGS__}; \ constexpr auto name = ::std::string_view{#__VA_ARGS__}; \
static_assert(!name.empty(), "Expression does not have a name."); \ static_assert(name.size() > 0, "Expression does not have a name."); \
constexpr auto size = name.size(); \ constexpr auto size = name.size(); \
return ::nameof::cstring<size>{name}; }() return ::nameof::cstring<size>{name}; }()

View file

@ -270,7 +270,6 @@ TEST_CASE("NAMEOF_CONST_ENUM") {
REQUIRE(cr_name == "RED"); REQUIRE(cr_name == "RED");
REQUIRE(NAMEOF_CONST_ENUM(Color::BLUE) == "BLUE"); REQUIRE(NAMEOF_CONST_ENUM(Color::BLUE) == "BLUE");
REQUIRE(NAMEOF_CONST_ENUM(cm[1]) == "GREEN"); REQUIRE(NAMEOF_CONST_ENUM(cm[1]) == "GREEN");
REQUIRE(NAMEOF_CONST_ENUM(static_cast<Color>(0)).empty());
constexpr Numbers no = Numbers::one; constexpr Numbers no = Numbers::one;
constexpr auto no_name = NAMEOF_CONST_ENUM(no); constexpr auto no_name = NAMEOF_CONST_ENUM(no);
@ -278,7 +277,6 @@ TEST_CASE("NAMEOF_CONST_ENUM") {
REQUIRE(NAMEOF_CONST_ENUM(Numbers::two) == "two"); REQUIRE(NAMEOF_CONST_ENUM(Numbers::two) == "two");
REQUIRE(NAMEOF_CONST_ENUM(Numbers::three) == "three"); REQUIRE(NAMEOF_CONST_ENUM(Numbers::three) == "three");
REQUIRE(NAMEOF_CONST_ENUM(Numbers::many) == "many"); REQUIRE(NAMEOF_CONST_ENUM(Numbers::many) == "many");
REQUIRE(NAMEOF_CONST_ENUM(static_cast<Numbers>(0)).empty());
constexpr Directions dr = Directions::Right; constexpr Directions dr = Directions::Right;
constexpr auto dr_name = NAMEOF_CONST_ENUM(dr); constexpr auto dr_name = NAMEOF_CONST_ENUM(dr);
@ -286,7 +284,6 @@ TEST_CASE("NAMEOF_CONST_ENUM") {
REQUIRE(NAMEOF_CONST_ENUM(Directions::Down) == "Down"); REQUIRE(NAMEOF_CONST_ENUM(Directions::Down) == "Down");
REQUIRE(dr_name == "Right"); REQUIRE(dr_name == "Right");
REQUIRE(NAMEOF_CONST_ENUM(Directions::Left) == "Left"); REQUIRE(NAMEOF_CONST_ENUM(Directions::Left) == "Left");
REQUIRE(NAMEOF_CONST_ENUM(static_cast<Directions>(0)).empty());
constexpr number nt = number::three; constexpr number nt = number::three;
constexpr auto nt_name = NAMEOF_CONST_ENUM(nt); constexpr auto nt_name = NAMEOF_CONST_ENUM(nt);
@ -294,7 +291,6 @@ TEST_CASE("NAMEOF_CONST_ENUM") {
REQUIRE(NAMEOF_CONST_ENUM(number::two) == "two"); REQUIRE(NAMEOF_CONST_ENUM(number::two) == "two");
REQUIRE(nt_name == "three"); REQUIRE(nt_name == "three");
REQUIRE(NAMEOF_CONST_ENUM(number::four) == "four"); REQUIRE(NAMEOF_CONST_ENUM(number::four) == "four");
REQUIRE(NAMEOF_CONST_ENUM(static_cast<number>(0)).empty());
} }
TEST_CASE("nameof_enum") { TEST_CASE("nameof_enum") {
@ -339,7 +335,6 @@ TEST_CASE("nameof_enum") {
REQUIRE(cr_name == "RED"); REQUIRE(cr_name == "RED");
REQUIRE(nameof::nameof_enum<Color::BLUE>() == "BLUE"); REQUIRE(nameof::nameof_enum<Color::BLUE>() == "BLUE");
REQUIRE(nameof::nameof_enum<cm[1]>() == "GREEN"); REQUIRE(nameof::nameof_enum<cm[1]>() == "GREEN");
REQUIRE(nameof::nameof_enum<static_cast<Color>(0)>().empty());
constexpr Numbers no = Numbers::one; constexpr Numbers no = Numbers::one;
constexpr auto no_name = nameof::nameof_enum<no>(); constexpr auto no_name = nameof::nameof_enum<no>();
@ -347,7 +342,6 @@ TEST_CASE("nameof_enum") {
REQUIRE(nameof::nameof_enum<Numbers::two>() == "two"); REQUIRE(nameof::nameof_enum<Numbers::two>() == "two");
REQUIRE(nameof::nameof_enum<Numbers::three>() == "three"); REQUIRE(nameof::nameof_enum<Numbers::three>() == "three");
REQUIRE(nameof::nameof_enum<Numbers::many>() == "many"); REQUIRE(nameof::nameof_enum<Numbers::many>() == "many");
REQUIRE(nameof::nameof_enum<static_cast<Numbers>(0)>().empty());
constexpr Directions dr = Directions::Right; constexpr Directions dr = Directions::Right;
constexpr auto dr_name = nameof::nameof_enum<dr>(); constexpr auto dr_name = nameof::nameof_enum<dr>();
@ -355,7 +349,6 @@ TEST_CASE("nameof_enum") {
REQUIRE(nameof::nameof_enum<Directions::Down>() == "Down"); REQUIRE(nameof::nameof_enum<Directions::Down>() == "Down");
REQUIRE(dr_name == "Right"); REQUIRE(dr_name == "Right");
REQUIRE(nameof::nameof_enum<Directions::Left>() == "Left"); REQUIRE(nameof::nameof_enum<Directions::Left>() == "Left");
REQUIRE(nameof::nameof_enum<static_cast<Directions>(0)>().empty());
constexpr number nt = number::three; constexpr number nt = number::three;
constexpr auto nt_name = nameof::nameof_enum<nt>(); constexpr auto nt_name = nameof::nameof_enum<nt>();
@ -363,7 +356,6 @@ TEST_CASE("nameof_enum") {
REQUIRE(nameof::nameof_enum<number::two>() == "two"); REQUIRE(nameof::nameof_enum<number::two>() == "two");
REQUIRE(nt_name == "three"); REQUIRE(nt_name == "three");
REQUIRE(nameof::nameof_enum<number::four>() == "four"); REQUIRE(nameof::nameof_enum<number::four>() == "four");
REQUIRE(nameof::nameof_enum<static_cast<number>(0)>().empty());
} }
} }