type_traits: make is_equality_comparable work with all major compilers

This commit is contained in:
Michele Caini
2021-01-15 09:48:48 +01:00
parent 446c8df3b4
commit 4aea1567db
2 changed files with 25 additions and 30 deletions

View File

@@ -430,36 +430,27 @@ using value_list_cat_t = typename value_list_cat<List...>::type;
namespace internal {
template<typename Type>
constexpr auto is_equality_comparable()
-> decltype(is_equality_comparable<Type>(choice<2>));
template<typename Type>
constexpr auto is_equality_comparable(choice_t<2>)
-> decltype(
std::declval<typename Type::mapped_type>(),
std::declval<Type>() == std::declval<Type>(),
std::conjunction<decltype(is_equality_comparable<typename Type::key_type>()), decltype(is_equality_comparable<typename Type::mapped_type>())>{}
);
template<typename Type>
constexpr auto is_equality_comparable(choice_t<1>)
-> decltype(
std::declval<typename Type::value_type>(),
std::declval<Type>() == std::declval<Type>(),
is_equality_comparable<typename Type::value_type>()
);
template<typename Type>
constexpr auto is_equality_comparable(choice_t<0>)
-> decltype(std::declval<Type>() == std::declval<Type>(), std::true_type{});
template<typename>
constexpr std::false_type is_equality_comparable(...);
[[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
template<typename Type>
[[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
-> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
template<typename Type>
[[nodiscard]] constexpr auto is_equality_comparable(choice_t<1>)
-> decltype(std::declval<typename Type::value_type>(), std::declval<Type>() == std::declval<Type>()) {
return is_equality_comparable<typename Type::value_type>(choice<2>);
}
template<typename Type>
[[nodiscard]] constexpr auto is_equality_comparable(choice_t<2>)
-> decltype(std::declval<typename Type::mapped_type>(), std::declval<Type>() == std::declval<Type>()) {
return is_equality_comparable<typename Type::key_type>(choice<2>) && is_equality_comparable<typename Type::mapped_type>(choice<2>);
}
}
@@ -477,7 +468,7 @@ constexpr std::false_type is_equality_comparable(...);
* @tparam Type Potentially equality comparable type.
*/
template<typename Type, typename = void>
struct is_equality_comparable: decltype(internal::is_equality_comparable<Type>()) {};
struct is_equality_comparable: std::bool_constant<internal::is_equality_comparable<Type>(choice<2>)> {};
/**

View File

@@ -92,11 +92,15 @@ TEST(TypeTraits, ValueList) {
TEST(TypeTraits, IsEqualityComparable) {
static_assert(entt::is_equality_comparable_v<int>);
static_assert(entt::is_equality_comparable_v<std::vector<int>>);
static_assert(entt::is_equality_comparable_v<std::vector<std::vector<int>>>);
static_assert(entt::is_equality_comparable_v<std::unordered_map<int, int>>);
static_assert(entt::is_equality_comparable_v<std::unordered_map<int, std::unordered_map<int, char>>>);
static_assert(!entt::is_equality_comparable_v<not_comparable>);
static_assert(!entt::is_equality_comparable_v<std::vector<not_comparable>>);
static_assert(!entt::is_equality_comparable_v<std::vector<std::vector<not_comparable>>>);
static_assert(!entt::is_equality_comparable_v<std::unordered_map<int, not_comparable>>);
static_assert(!entt::is_equality_comparable_v<std::unordered_map<int, std::unordered_map<int, not_comparable>>>);
static_assert(!entt::is_equality_comparable_v<void>);
}