diff --git a/include/nameof.hpp b/include/nameof.hpp index e0c7a6b..c85cd12 100644 --- a/include/nameof.hpp +++ b/include/nameof.hpp @@ -79,12 +79,15 @@ static_assert(NAMEOF_ENUM_RANGE_MAX > NAMEOF_ENUM_RANGE_MIN, namespace detail { template -struct check final { - using type = void; +struct identity final { + using type = T; }; template -using check_t = typename check::type; +using remove_cvref_t = std::remove_cv_t>; + +template +using enable_if_enum_t = std::enable_if_t>, R>; template [[nodiscard]] constexpr std::string_view nameof_impl(std::string_view name, bool remove_template_suffix = true) noexcept { @@ -162,9 +165,9 @@ template (name.front() >= 'A' && name.front() <= 'Z') || (name.front() == '_'))) { return name; - } else { - return {}; // Invalid name. } + + return {}; // Invalid name. } template @@ -198,11 +201,6 @@ template return names; } -template -struct identity final { - using type = T; -}; - template [[nodiscard]] constexpr std::string_view nameof_type_impl() noexcept { #if defined(__clang__) @@ -224,30 +222,29 @@ template // Obtains simple (unqualified) string enum name of enum variable. template -[[nodiscard]] constexpr std::enable_if_t>, std::string_view> nameof_enum(E value) noexcept { - using D = std::decay_t; +[[nodiscard]] constexpr detail::enable_if_enum_t nameof_enum(E value) noexcept { + using D = detail::remove_cvref_t; static_assert(std::is_enum_v, "nameof::nameof_enum requires enum type."); static_assert(enum_range::min > (std::numeric_limits::min)(), "nameof::enum_range requires min must be greater than INT_MIN."); static_assert(enum_range::max < (std::numeric_limits::max)(), "nameof::enum_range requires max must be less than INT_MAX."); static_assert(enum_range::max > enum_range::min, "nameof::enum_range requires max > min."); using U = std::underlying_type_t; - constexpr int max = enum_range::max < (std::numeric_limits::max)() ? enum_range::max : (std::numeric_limits::max)(); - constexpr int min = enum_range::min > (std::numeric_limits::min)() ? enum_range::min : (std::numeric_limits::min)(); - constexpr auto range = std::make_integer_sequence{}; - constexpr auto names = detail::enum_names_impl(range); + constexpr auto max = enum_range::max < (std::numeric_limits::max)() ? enum_range::max : (std::numeric_limits::max)(); + constexpr auto min = enum_range::min > (std::numeric_limits::min)() ? enum_range::min : (std::numeric_limits::min)(); + constexpr auto names = detail::enum_names_impl(std::make_integer_sequence{}); - if (auto i = static_cast(static_cast(value) - min); i < names.size()) { + if (auto i = static_cast((static_cast(value) - min)); i < names.size()) { return names[i]; - } else { - return {}; // Value out of range. } + + return {}; // Value out of range. } // 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. template -[[nodiscard]] constexpr std::enable_if_t>, std::string_view> nameof_enum() noexcept { - using D = std::decay_t; +[[nodiscard]] constexpr detail::enable_if_enum_t nameof_enum() noexcept { + using D = detail::remove_cvref_t; static_assert(std::is_enum_v, "nameof::nameof_enum requires enum type."); return detail::nameof_enum_impl(); @@ -256,7 +253,7 @@ template // Obtains string name of type, reference and cv-qualifiers are ignored. template [[nodiscard]] constexpr std::string_view nameof_type() noexcept { - return detail::nameof_type_impl>>>(); + return detail::nameof_type_impl>>(); } // Obtains string name of full type, with reference and cv-qualifiers. @@ -268,13 +265,13 @@ template } // namespace nameof // Obtains simple (unqualified) string name of variable, function, enum, macro. -#define NAMEOF(...) ::nameof::detail::nameof_impl<::nameof::detail::check_t>(#__VA_ARGS__) +#define NAMEOF(...) ::nameof::detail::nameof_impl<::std::void_t>(#__VA_ARGS__) // Obtains simple (unqualified) full (with template suffix) string name of variable, function, enum, macro. -#define NAMEOF_FULL(...) ::nameof::detail::nameof_impl<::nameof::detail::check_t>(#__VA_ARGS__, false) +#define NAMEOF_FULL(...) ::nameof::detail::nameof_impl<::std::void_t>(#__VA_ARGS__, false) // Obtains raw string name of variable, function, enum, macro. -#define NAMEOF_RAW(...) ::nameof::detail::nameof_raw_impl<::nameof::detail::check_t>(#__VA_ARGS__) +#define NAMEOF_RAW(...) ::nameof::detail::nameof_raw_impl<::std::void_t>(#__VA_ARGS__) // Obtains simple (unqualified) string enum name of enum variable. #define NAMEOF_ENUM(...) ::nameof::nameof_enum(__VA_ARGS__)