Ver Fonte

type_traits: make is_equality_comparable work with all major compilers

Michele Caini há 5 anos atrás
pai
commit
4aea1567db
2 ficheiros alterados com 17 adições e 22 exclusões
  1. 13 22
      src/entt/core/type_traits.hpp
  2. 4 0
      test/entt/core/type_traits.cpp

+ 13 - 22
src/entt/core/type_traits.hpp

@@ -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>
+[[nodiscard]] constexpr bool is_equality_comparable(...) { return false; }
 
 
 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>())>{}
-);
+[[nodiscard]] constexpr auto is_equality_comparable(choice_t<0>)
+-> decltype(std::declval<Type>() == std::declval<Type>()) { return true; }
 
 
 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>()
-);
+[[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>
-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 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>)> {};
 
 
 /**

+ 4 - 0
test/entt/core/type_traits.cpp

@@ -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>);
 }