improve nameof_enum (#20)

improve nameof_enum
This commit is contained in:
Daniil Goncharov 2020-05-23 17:56:46 +05:00 committed by GitHub
parent e2a56fa18a
commit a47f23bc6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -46,7 +46,6 @@
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(push) # pragma warning(push)
# pragma warning(disable : 26495) // Variable 'nameof::cstring<N>::chars_' is uninitialized. # pragma warning(disable : 26495) // Variable 'nameof::cstring<N>::chars_' is uninitialized.
# pragma warning(disable : 26451) // Arithmetic overflow: 'strings_[static_cast<U>(value) - min_v<E>]' and 'indexes_[static_cast<U>(value) - min_v<E>]' using operator '-' on a 4 byte value and then casting the result to a 8 byte value.
#endif #endif
// Checks nameof_type compiler compatibility. // Checks nameof_type compiler compatibility.
@ -485,7 +484,7 @@ constexpr auto indexes(std::integer_sequence<int, I...>) noexcept {
} }
template <typename E> template <typename E>
inline constexpr bool sparsity_v = (sizeof(const char*) * range_size_v<E>) > (sizeof(index_t<E>) * range_size_v<E> + sizeof(const char*) * count_v<E>); inline constexpr auto indexes_v = indexes<E>(std::make_integer_sequence<int, range_size_v<E>>{});
template <typename E, int... I> template <typename E, int... I>
constexpr auto strings(std::integer_sequence<int, I...>) noexcept { constexpr auto strings(std::integer_sequence<int, I...>) noexcept {
@ -501,6 +500,9 @@ constexpr auto strings(std::index_sequence<I...>) noexcept {
return std::array<const char*, sizeof...(I)>{{enum_name_v<E, values_v<E>[I]>.data()...}}; return std::array<const char*, sizeof...(I)>{{enum_name_v<E, values_v<E>[I]>.data()...}};
} }
template <typename E>
inline constexpr bool sparsity_v = (sizeof(const char*) * range_size_v<E>) > (sizeof(index_t<E>) * range_size_v<E> + sizeof(const char*) * count_v<E>);
template <typename E> template <typename E>
constexpr auto strings() noexcept { constexpr auto strings() noexcept {
static_assert(is_enum_v<E>, "nameof::detail::strings requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::strings requires enum type.");
@ -513,28 +515,7 @@ constexpr auto strings() noexcept {
} }
template <typename E> template <typename E>
class enum_traits { inline static constexpr auto strings_v = strings<E>();
static_assert(is_enum_v<E>, "nameof::enum_traits requires enum type.");
static_assert(count_v<E> > 0, "nameof::enum_range requires enum implementation and valid max and min.");
using U = std::underlying_type_t<E>;
inline static constexpr auto strings_ = strings<E>();
inline static constexpr auto indexes_ = indexes<E>(std::make_integer_sequence<int, range_size_v<E>>{});
public:
static constexpr std::string_view name(E value) noexcept {
if (static_cast<U>(value) >= static_cast<U>(min_v<E>) && static_cast<U>(value) <= static_cast<U>(max_v<E>)) {
if constexpr (sparsity_v<E>) {
if (const auto i = indexes_[static_cast<U>(value) - min_v<E>]; i != invalid_index_v<E>) {
return strings_[i];
}
} else {
return strings_[static_cast<U>(value) - min_v<E>];
}
}
return {}; // Value out of range.
}
};
} // namespace nameof::detail::enums } // namespace nameof::detail::enums
@ -569,8 +550,23 @@ inline constexpr bool is_nameof_enum_supported = detail::nameof_enum_supported<v
// Obtains simple (unqualified) string enum name of enum variable. // Obtains simple (unqualified) string enum name of enum variable.
template <typename E> template <typename E>
[[nodiscard]] constexpr auto nameof_enum(E value) noexcept -> detail::enable_if_enum_t<E, std::string_view> { [[nodiscard]] constexpr auto nameof_enum(E value) noexcept -> detail::enable_if_enum_t<E, std::string_view> {
using namespace detail::enums;
using D = detail::remove_cvref_t<E>;
using U = std::underlying_type_t<D>;
static_assert(detail::nameof_enum_supported<E>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(detail::nameof_enum_supported<E>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
return detail::enums::enum_traits<detail::remove_cvref_t<E>>::name(value); static_assert(count_v<D> > 0, "nameof::nameof_enum requires enum implementation and valid max and min.");
if (const auto i = static_cast<int>(value) - min_v<D>; static_cast<U>(value) >= static_cast<U>(min_v<E>) && static_cast<U>(value) <= static_cast<U>(max_v<E>)) {
if constexpr (sparsity_v<D>) {
if (const auto idx = indexes_v<D>[i]; idx != invalid_index_v<D>) {
return strings_v<D>[idx];
}
} else {
return strings_v<D>[i];
}
}
return {}; // Value out of range.
} }
// Obtains simple (unqualified) string enum name of static storage enum variable. // Obtains simple (unqualified) string enum name of static storage enum variable.
@ -578,7 +574,6 @@ template <typename E>
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 -> detail::enable_if_enum_t<decltype(V), std::string_view> {
using E = detail::remove_cvref_t<decltype(V)>; using E = detail::remove_cvref_t<decltype(V)>;
static_assert(detail::nameof_enum_supported<E>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
constexpr std::string_view name = detail::enum_name_v<E, V>; constexpr std::string_view name = detail::enum_name_v<E, V>;
static_assert(name.size() > 0, "Enum value does not have a name."); static_assert(name.size() > 0, "Enum value does not have a name.");
@ -645,7 +640,7 @@ template <typename T>
return nameof_raw; }() return nameof_raw; }()
// Obtains simple (unqualified) string enum name of enum variable. // 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<decltype(__VA_ARGS__)>>(__VA_ARGS__)
// 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.