* add sep param to nameof_enum_flag

* fix noexcept
This commit is contained in:
neargye 2023-06-14 02:44:15 +04:00
parent 8a6813f242
commit f2522c2cc0
2 changed files with 19 additions and 32 deletions

View file

@ -211,6 +211,7 @@
flag = AnimalFlags::CanFly | AnimalFlags::Endangered; flag = AnimalFlags::CanFly | AnimalFlags::Endangered;
NAMEOF_ENUM_FLAG(flag) -> "CanFly|Endangered" NAMEOF_ENUM_FLAG(flag) -> "CanFly|Endangered"
nameof_enum_flag(flag) -> "CanFly|Endangered" nameof_enum_flag(flag) -> "CanFly|Endangered"
nameof_enum_flag(flag, '$') -> "CanFly$Endangered"
NAMEOF_ENUM(HasClaws | CanFly) -> "" NAMEOF_ENUM(HasClaws | CanFly) -> ""
nameof_enum(HasClaws | CanFly) -> "" nameof_enum(HasClaws | CanFly) -> ""

View file

@ -47,15 +47,15 @@
#include <utility> #include <utility>
#if !defined(NAMEOF_USING_ALIAS_STRING) #if !defined(NAMEOF_USING_ALIAS_STRING)
#include <string> # include <string>
#endif #endif
#if !defined(NAMEOF_USING_ALIAS_STRING_VIEW) #if !defined(NAMEOF_USING_ALIAS_STRING_VIEW)
#include <string_view> # include <string_view>
#endif #endif
#if __has_include(<cxxabi.h>) #if __has_include(<cxxabi.h>)
#include <cxxabi.h> # include <cxxabi.h>
#include <cstdlib> # include <cstdlib>
#endif #endif
#if defined(__clang__) #if defined(__clang__)
@ -174,7 +174,6 @@ static_assert(NAMEOF_ENUM_RANGE_MAX > NAMEOF_ENUM_RANGE_MIN, "NAMEOF_ENUM_RANGE_
template <typename E> template <typename E>
constexpr string_view enum_name(E) noexcept { constexpr string_view enum_name(E) noexcept {
static_assert(std::is_enum_v<E>, "nameof::customize::enum_name requires enum type."); static_assert(std::is_enum_v<E>, "nameof::customize::enum_name requires enum type.");
return {}; return {};
} }
@ -413,7 +412,6 @@ std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& o
for (const auto c : srt) { for (const auto c : srt) {
os.put(c); os.put(c);
} }
return os; return os;
} }
@ -853,11 +851,11 @@ using enable_if_has_short_name_t = std::enable_if_t<!std::is_array_v<T> && !std:
template <typename... T> template <typename... T>
constexpr auto n() noexcept { constexpr auto n() noexcept {
# if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
[[maybe_unused]] constexpr auto custom_name = customize::type_name<typename T::type...>(); [[maybe_unused]] constexpr auto custom_name = customize::type_name<typename T::type...>();
#else #else
[[maybe_unused]] constexpr auto custom_name = customize::type_name<T...>(); [[maybe_unused]] constexpr auto custom_name = customize::type_name<T...>();
# endif #endif
if constexpr (custom_name.empty() && nameof_type_supported<T...>::value) { if constexpr (custom_name.empty() && nameof_type_supported<T...>::value) {
#if defined(__clang__) #if defined(__clang__)
@ -870,7 +868,6 @@ constexpr auto n() noexcept {
constexpr auto name = string_view{}; constexpr auto name = string_view{};
#endif #endif
return cstring<name.size()>{name}; return cstring<name.size()>{name};
} else { } else {
return cstring<custom_name.size()>{custom_name}; return cstring<custom_name.size()>{custom_name};
} }
@ -927,16 +924,15 @@ string nameof_short_type_rtti(const char* tn) {
} }
#else #else
template <typename T> template <typename T>
string nameof_type_rtti(const char* tn) noexcept { string nameof_type_rtti(const char* tn) {
static_assert(nameof_type_rtti_supported<T>::value, "nameof::nameof_type_rtti unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(nameof_type_rtti_supported<T>::value, "nameof::nameof_type_rtti unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
const auto name = string_view{tn}; const auto name = string_view{tn};
assert(!name.empty() && "Type does not have a name."); assert(!name.empty() && "Type does not have a name.");
return {name.data(), name.size()}; return {name.data(), name.size()};
} }
template <typename T> template <typename T>
string nameof_full_type_rtti(const char* tn) noexcept { string nameof_full_type_rtti(const char* tn) {
static_assert(nameof_type_rtti_supported<T>::value, "nameof::nameof_type_rtti unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(nameof_type_rtti_supported<T>::value, "nameof::nameof_type_rtti unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
auto name = string{tn}; auto name = string{tn};
assert(!name.empty() && "Type does not have a name."); assert(!name.empty() && "Type does not have a name.");
@ -952,16 +948,14 @@ string nameof_full_type_rtti(const char* tn) noexcept {
if constexpr (std::is_rvalue_reference_v<T>) { if constexpr (std::is_rvalue_reference_v<T>) {
name.append("&&"); name.append("&&");
} }
return name; return name;
} }
template <typename T, enable_if_has_short_name_t<T, int> = 0> template <typename T, enable_if_has_short_name_t<T, int> = 0>
string nameof_short_type_rtti(const char* tn) noexcept { string nameof_short_type_rtti(const char* tn) {
static_assert(nameof_type_rtti_supported<T>::value, "nameof::nameof_type_rtti unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(nameof_type_rtti_supported<T>::value, "nameof::nameof_type_rtti unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
const auto name = pretty_name(tn); const auto name = pretty_name(tn);
assert(!name.empty() && "Type does not have a short name."); assert(!name.empty() && "Type does not have a short name.");
return {name.data(), name.size()}; return {name.data(), name.size()};
} }
#endif #endif
@ -1011,9 +1005,9 @@ constexpr auto get_member_name() noexcept {
constexpr bool is_defined = sizeof(decltype(get_base_type(V))) != 0; constexpr bool is_defined = sizeof(decltype(get_base_type(V))) != 0;
static_assert(is_defined, "nameof::nameof_member member name can use only if the struct is already fully defined. Please use NAMEOF macro, or separate definition and declaration."); static_assert(is_defined, "nameof::nameof_member member name can use only if the struct is already fully defined. Please use NAMEOF macro, or separate definition and declaration.");
if constexpr (is_defined) { if constexpr (is_defined) {
return n<V, &(union_type_holder<decltype(get_base_type(V))>::value.f.*V)>(); return n<V, &(union_type_holder<decltype(get_base_type(V))>::value.f.*V)>();
} else { } else {
return ""; return "";
} }
} }
} }
@ -1083,8 +1077,8 @@ template <typename E>
static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
static_assert(detail::count_v<D> > 0, "nameof::nameof_enum requires enum implementation and valid max and min."); static_assert(detail::count_v<D> > 0, "nameof::nameof_enum requires enum implementation and valid max and min.");
const bool valid = static_cast<U>(value) >= static_cast<U>(detail::min_v<D>) && static_cast<U>(value) <= static_cast<U>(detail::max_v<D>); if (static_cast<U>(value) >= static_cast<U>(detail::min_v<D>) && static_cast<U>(value) <= static_cast<U>(detail::max_v<D>)) {
if (const auto i = static_cast<int>(value) - detail::min_v<D>; valid) { const auto i = static_cast<int>(value) - detail::min_v<D>;
if constexpr (detail::is_sparse_v<D>) { if constexpr (detail::is_sparse_v<D>) {
if (const auto idx = detail::indexes_v<D>[i]; idx != detail::invalid_index_v<D>) { if (const auto idx = detail::indexes_v<D>[i]; idx != detail::invalid_index_v<D>) {
return detail::strings_v<D>[idx]; return detail::strings_v<D>[idx];
@ -1093,7 +1087,6 @@ template <typename E>
return detail::strings_v<D>[static_cast<std::size_t>(i)]; return detail::strings_v<D>[static_cast<std::size_t>(i)];
} }
} }
return {}; // Value out of range. return {}; // Value out of range.
} }
@ -1101,17 +1094,18 @@ template <typename E>
template <typename E> template <typename E>
[[nodiscard]] auto nameof_enum_or(E value, string_view default_value) -> detail::enable_if_enum_t<E, string> { [[nodiscard]] auto nameof_enum_or(E value, string_view default_value) -> detail::enable_if_enum_t<E, string> {
using D = std::decay_t<E>; using D = std::decay_t<E>;
static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum_or unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
static_assert(detail::count_v<D> > 0, "nameof::nameof_enum_or requires enum implementation and valid max and min.");
if (auto v = nameof_enum<D>(value); !v.empty()) { if (auto v = nameof_enum<D>(value); !v.empty()) {
return string{v.data(), v.size()}; return string{v.data(), v.size()};
} }
return string{default_value.data(), default_value.size()}; return string{default_value.data(), default_value.size()};
} }
// Obtains name of enum-flags variable. // 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, char sep = '|') -> detail::enable_if_enum_t<E, string> {
using D = std::decay_t<E>; using D = std::decay_t<E>;
using U = std::underlying_type_t<D>; using U = std::underlying_type_t<D>;
static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum_flag unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum_flag unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
@ -1125,7 +1119,7 @@ template <typename E>
if (const auto n = detail::strings_v<D, true>[i]; n != nullptr) { if (const auto n = detail::strings_v<D, true>[i]; n != nullptr) {
check_value |= v; check_value |= v;
if (!name.empty()) { if (!name.empty()) {
name.append(1, '|'); name.append(1, sep);
} }
name.append(n); name.append(n);
} else { } else {
@ -1134,11 +1128,9 @@ template <typename E>
} }
} }
const bool valid = check_value != 0 && check_value == static_cast<U>(value); if (check_value != 0 && check_value == static_cast<U>(value)) {
if (valid) {
return name; return name;
} }
return {}; // Invalid value or out of range. return {}; // Invalid value or out of range.
} }
@ -1150,7 +1142,6 @@ template <auto V>
static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(detail::nameof_enum_supported<D>::value, "nameof::nameof_enum unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
constexpr string_view name = detail::enum_name_v<D, V>; constexpr string_view name = detail::enum_name_v<D, V>;
static_assert(!name.empty(), "Enum value does not have a name."); static_assert(!name.empty(), "Enum value does not have a name.");
return name; return name;
} }
@ -1161,7 +1152,6 @@ template <typename T>
using U = detail::identity<detail::remove_cvref_t<T>>; using U = detail::identity<detail::remove_cvref_t<T>>;
constexpr string_view name = detail::type_name_v<U>; constexpr string_view name = detail::type_name_v<U>;
static_assert(!name.empty(), "Type does not have a name."); static_assert(!name.empty(), "Type does not have a name.");
return name; return name;
} }
@ -1172,7 +1162,6 @@ template <typename T>
using U = detail::identity<T>; using U = detail::identity<T>;
constexpr string_view name = detail::type_name_v<U>; constexpr string_view name = detail::type_name_v<U>;
static_assert(!name.empty(), "Type does not have a full name."); static_assert(!name.empty(), "Type does not have a full name.");
return name; return name;
} }
@ -1183,7 +1172,6 @@ template <typename T>
using U = detail::identity<detail::remove_cvref_t<T>>; using U = detail::identity<detail::remove_cvref_t<T>>;
constexpr string_view name = detail::pretty_name(detail::type_name_v<U>); constexpr string_view name = detail::pretty_name(detail::type_name_v<U>);
static_assert(!name.empty(), "Type does not have a short name."); static_assert(!name.empty(), "Type does not have a short name.");
return name; return name;
} }
@ -1193,7 +1181,6 @@ template <auto V>
static_assert(detail::nameof_member_supported<decltype(V)>::value, "nameof::nameof_member unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(detail::nameof_member_supported<decltype(V)>::value, "nameof::nameof_member unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
constexpr string_view name = detail::member_name_v<V>; constexpr string_view name = detail::member_name_v<V>;
static_assert(!name.empty(), "Member does not have a name."); static_assert(!name.empty(), "Member does not have a name.");
return name; return name;
} }
@ -1203,7 +1190,6 @@ template <auto V>
static_assert(detail::nameof_pointer_supported<decltype(V)>::value, "nameof::nameof_pointer unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility)."); static_assert(detail::nameof_pointer_supported<decltype(V)>::value, "nameof::nameof_pointer unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
constexpr string_view name = detail::pointer_name_v<V>; constexpr string_view name = detail::pointer_name_v<V>;
static_assert(!name.empty(), "Pointer does not have a name."); static_assert(!name.empty(), "Pointer does not have a name.");
return name; return name;
} }