From a47f23bc6d2e1e4e6ec920af864bfab448b14650 Mon Sep 17 00:00:00 2001 From: Daniil Goncharov Date: Sat, 23 May 2020 17:56:46 +0500 Subject: [PATCH] improve nameof_enum (#20) improve nameof_enum --- include/nameof.hpp | 49 +++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/include/nameof.hpp b/include/nameof.hpp index 6cec454..bbf4e1d 100644 --- a/include/nameof.hpp +++ b/include/nameof.hpp @@ -46,7 +46,6 @@ #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 26495) // Variable 'nameof::cstring::chars_' is uninitialized. -# pragma warning(disable : 26451) // Arithmetic overflow: 'strings_[static_cast(value) - min_v]' and 'indexes_[static_cast(value) - min_v]' using operator '-' on a 4 byte value and then casting the result to a 8 byte value. #endif // Checks nameof_type compiler compatibility. @@ -485,7 +484,7 @@ constexpr auto indexes(std::integer_sequence) noexcept { } template -inline constexpr bool sparsity_v = (sizeof(const char*) * range_size_v) > (sizeof(index_t) * range_size_v + sizeof(const char*) * count_v); +inline constexpr auto indexes_v = indexes(std::make_integer_sequence>{}); template constexpr auto strings(std::integer_sequence) noexcept { @@ -501,6 +500,9 @@ constexpr auto strings(std::index_sequence) noexcept { return std::array{{enum_name_v[I]>.data()...}}; } +template +inline constexpr bool sparsity_v = (sizeof(const char*) * range_size_v) > (sizeof(index_t) * range_size_v + sizeof(const char*) * count_v); + template constexpr auto strings() noexcept { static_assert(is_enum_v, "nameof::detail::strings requires enum type."); @@ -513,28 +515,7 @@ constexpr auto strings() noexcept { } template -class enum_traits { - static_assert(is_enum_v, "nameof::enum_traits requires enum type."); - static_assert(count_v > 0, "nameof::enum_range requires enum implementation and valid max and min."); - using U = std::underlying_type_t; - inline static constexpr auto strings_ = strings(); - inline static constexpr auto indexes_ = indexes(std::make_integer_sequence>{}); - - public: - static constexpr std::string_view name(E value) noexcept { - if (static_cast(value) >= static_cast(min_v) && static_cast(value) <= static_cast(max_v)) { - if constexpr (sparsity_v) { - if (const auto i = indexes_[static_cast(value) - min_v]; i != invalid_index_v) { - return strings_[i]; - } - } else { - return strings_[static_cast(value) - min_v]; - } - } - - return {}; // Value out of range. - } -}; +inline static constexpr auto strings_v = strings(); } // namespace nameof::detail::enums @@ -569,8 +550,23 @@ inline constexpr bool is_nameof_enum_supported = detail::nameof_enum_supported [[nodiscard]] constexpr auto nameof_enum(E value) noexcept -> detail::enable_if_enum_t { + using namespace detail::enums; + using D = detail::remove_cvref_t; + using U = std::underlying_type_t; static_assert(detail::nameof_enum_supported::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); - return detail::enums::enum_traits>::name(value); + static_assert(count_v > 0, "nameof::nameof_enum requires enum implementation and valid max and min."); + + if (const auto i = static_cast(value) - min_v; static_cast(value) >= static_cast(min_v) && static_cast(value) <= static_cast(max_v)) { + if constexpr (sparsity_v) { + if (const auto idx = indexes_v[i]; idx != invalid_index_v) { + return strings_v[idx]; + } + } else { + return strings_v[i]; + } + } + + return {}; // Value out of range. } // Obtains simple (unqualified) string enum name of static storage enum variable. @@ -578,7 +574,6 @@ template template [[nodiscard]] constexpr auto nameof_enum() noexcept -> detail::enable_if_enum_t { using E = detail::remove_cvref_t; - static_assert(detail::nameof_enum_supported::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); constexpr std::string_view name = detail::enum_name_v; static_assert(name.size() > 0, "Enum value does not have a name."); @@ -645,7 +640,7 @@ template return nameof_raw; }() // Obtains simple (unqualified) string enum name of enum variable. -#define NAMEOF_ENUM(...) ::nameof::nameof_enum(__VA_ARGS__) +#define NAMEOF_ENUM(...) ::nameof::nameof_enum<::std::decay_t>(__VA_ARGS__) // 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.