fix clang llvm-project#50055(reviews.llvm.org/D130058)

This commit is contained in:
neargye 2022-08-09 15:28:23 +04:00
parent c04b72fc51
commit c44b65d57d

View file

@ -559,26 +559,39 @@ constexpr auto n() noexcept {
template <typename E, E V> template <typename E, E V>
inline constexpr auto enum_name_v = n<E, V>(); inline constexpr auto enum_name_v = n<E, V>();
template <typename E, auto V> template <typename E, E V>
constexpr bool is_valid() noexcept { constexpr bool valid() noexcept {
static_assert(is_enum_v<E>, "nameof::detail::is_valid requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::is_valid requires enum type.");
return n<E, static_cast<E>(V)>().size() != 0; return n<E, static_cast<E>(V)>().size() != 0;
} }
template <typename E, int O, bool IsFlags = false, typename U = std::underlying_type_t<E>> template <typename E, auto V, typename = void>
struct is_valid : std::false_type {};
template <typename E, auto V>
struct is_valid<E, V, std::void_t<decltype(valid<E, static_cast<E>(V)>())>> : std::bool_constant<valid<E, static_cast<E>(V)>()> {};
template <typename E, int O, bool IsFlags, typename U = std::underlying_type_t<E>>
constexpr U ualue(std::size_t i) noexcept {
static_assert(is_enum_v<E>, "nameof::detail::ualue requires enum type.");
if constexpr (std::is_same_v<U, bool>) { // bool special case
static_assert(O == 0, "nameof::detail::ualue requires valid offset.");
return static_cast<U>(i);
} else if constexpr (IsFlags) {
return static_cast<U>(U{1} << static_cast<U>(static_cast<int>(i) + O));
} else {
return static_cast<U>(static_cast<int>(i) + O);
}
}
template <typename E, int O, bool IsFlags, typename U = std::underlying_type_t<E>>
constexpr E value(std::size_t i) noexcept { constexpr E value(std::size_t i) noexcept {
static_assert(is_enum_v<E>, "nameof::detail::value requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::value requires enum type.");
if constexpr (std::is_same_v<U, bool>) { // bool special case return static_cast<E>(ualue<E, O, IsFlags>(i));
static_assert(O == 0, "nameof::detail::value requires valid offset.");
return static_cast<E>(i);
} else if constexpr (IsFlags) {
return static_cast<E>(U{1} << static_cast<U>(static_cast<int>(i) + O));
} else {
return static_cast<E>(static_cast<int>(i) + O);
}
} }
template <typename E, bool IsFlags, typename U = std::underlying_type_t<E>> template <typename E, bool IsFlags, typename U = std::underlying_type_t<E>>
@ -638,7 +651,7 @@ constexpr std::size_t values_count(const bool (&valid)[N]) noexcept {
template <typename E, bool IsFlags, int Min, std::size_t... I> template <typename E, bool IsFlags, int Min, std::size_t... I>
constexpr auto values(std::index_sequence<I...>) noexcept { constexpr auto values(std::index_sequence<I...>) noexcept {
static_assert(is_enum_v<E>, "nameof::detail::values requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::values requires enum type.");
constexpr bool valid[sizeof...(I)] = {is_valid<E, value<E, Min, IsFlags>(I)>()...}; constexpr bool valid[sizeof...(I)] = {is_valid<E, ualue<E, Min, IsFlags>(I)>::value...};
constexpr std::size_t count = values_count(valid); constexpr std::size_t count = values_count(valid);
if constexpr (count > 0) { if constexpr (count > 0) {