add nameof_enum_or

This commit is contained in:
neargye 2022-07-26 18:17:36 +04:00
parent f32bbb0f09
commit 59411bf519
2 changed files with 46 additions and 5 deletions

View file

@ -979,7 +979,7 @@ inline constexpr bool is_nameof_member_supported = detail::nameof_member_support
// Checks is nameof_enum supported compiler. // Checks is nameof_enum supported compiler.
inline constexpr bool is_nameof_enum_supported = detail::nameof_enum_supported<void>::value; inline constexpr bool is_nameof_enum_supported = detail::nameof_enum_supported<void>::value;
// Obtains simple (unqualified) name of enum variable. // Obtains name of enum variable.
template <typename E> template <typename E>
[[nodiscard]] constexpr auto nameof_enum(E value) noexcept -> detail::enable_if_enum_t<E, string_view> { [[nodiscard]] constexpr auto nameof_enum(E value) noexcept -> detail::enable_if_enum_t<E, string_view> {
using D = std::decay_t<E>; using D = std::decay_t<E>;
@ -998,11 +998,22 @@ template <typename E>
} }
} }
assert(valid && "enum variable does not have a name.");
return {}; // Value out of range. return {}; // Value out of range.
} }
// Obtains simple (unqualified) name of enum-flags variable. // Obtains name of enum variable or default value if enum variable out of range.
template <typename E>
[[nodiscard]] auto nameof_enum_or(E value, string_view default_value) noexcept -> detail::enable_if_enum_t<E, string> {
using D = std::decay_t<E>;
if (auto v = nameof_enum<D>(value); !v.empty()) {
return string{v.data(), v.size()};
}
return string{default_value.data(), default_value.size()};
}
// Obtains name of enum-flags variable.
template <typename E> template <typename E>
[[nodiscard]] auto nameof_enum_flag(E value) -> detail::enable_if_enum_t<E, string> { [[nodiscard]] auto nameof_enum_flag(E value) -> detail::enable_if_enum_t<E, string> {
using D = std::decay_t<E>; using D = std::decay_t<E>;
@ -1032,11 +1043,10 @@ template <typename E>
return name; return name;
} }
assert(valid && "enum-flags variable does not have a name.");
return {}; // Invalid value or out of range. return {}; // Invalid value or out of range.
} }
// Obtains simple (unqualified) name of static storage enum variable. // Obtains 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), string_view> { [[nodiscard]] constexpr auto nameof_enum() noexcept -> detail::enable_if_enum_t<decltype(V), string_view> {
@ -1123,6 +1133,9 @@ template <auto V>
// Obtains name of enum variable. // Obtains name of enum variable.
#define NAMEOF_ENUM(...) ::nameof::nameof_enum<::std::decay_t<decltype(__VA_ARGS__)>>(__VA_ARGS__) #define NAMEOF_ENUM(...) ::nameof::nameof_enum<::std::decay_t<decltype(__VA_ARGS__)>>(__VA_ARGS__)
// Obtains name of enum variable or default value if enum variable out of range.
#define NAMEOF_ENUM_OR(...) ::nameof::nameof_enum_or(__VA_ARGS__)
// Obtains name of static storage enum variable. // Obtains 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.
#define NAMEOF_ENUM_CONST(...) ::nameof::nameof_enum<__VA_ARGS__>() #define NAMEOF_ENUM_CONST(...) ::nameof::nameof_enum<__VA_ARGS__>()

View file

@ -107,6 +107,12 @@ struct nameof::customize::enum_range<number> {
static_assert(max > min, "nameof::enum_range<number> requires max > min."); static_assert(max > min, "nameof::enum_range<number> requires max > min.");
}; };
enum class OutOfRange {
too_low = NAMEOF_ENUM_RANGE_MIN - 1,
required_to_work = 0,
too_high = NAMEOF_ENUM_RANGE_MAX + 1
};
struct TestRtti{ struct TestRtti{
struct Base { virtual ~Base() = default; }; struct Base { virtual ~Base() = default; };
struct Derived : Base {}; struct Derived : Base {};
@ -442,6 +448,28 @@ TEST_CASE("NAMEOF_ENUM_FLAG") {
NAMEOF_DEBUG_REQUIRE(NAMEOF_ENUM_FLAG(static_cast<BigFlags>((static_cast<std::uint64_t>(0x1) << 63) | 2)).empty()); NAMEOF_DEBUG_REQUIRE(NAMEOF_ENUM_FLAG(static_cast<BigFlags>((static_cast<std::uint64_t>(0x1) << 63) | 2)).empty());
} }
TEST_CASE("nameof_enum_or") {
OutOfRange low = OutOfRange::too_low;
OutOfRange high = OutOfRange::too_high;
auto low_name = nameof::nameof_enum_or(low, "-121");
auto high_name = nameof::nameof_enum_or(high, "121");
constexpr OutOfRange oor[] = {OutOfRange::too_high, OutOfRange::too_low};
REQUIRE(low_name == "-121");
REQUIRE(high_name == "121");
REQUIRE(nameof::nameof_enum_or(oor[0], "121") == "121");
}
TEST_CASE("NAMEOF_ENUM_OR") {
OutOfRange low = OutOfRange::too_low;
OutOfRange high = OutOfRange::too_high;
auto low_name = NAMEOF_ENUM_OR(low, "-121");
auto high_name = NAMEOF_ENUM_OR(high, "121");
constexpr OutOfRange oor[] = {OutOfRange::too_high, OutOfRange::too_low};
REQUIRE(low_name == "-121");
REQUIRE(high_name == "121");
REQUIRE(NAMEOF_ENUM_OR(oor[0], "121") == "121");
}
#endif #endif
#if defined(NAMEOF_TYPE_SUPPORTED) #if defined(NAMEOF_TYPE_SUPPORTED)