diff --git a/src/entt/core/type_traits.hpp b/src/entt/core/type_traits.hpp index b371c8210..184756299 100644 --- a/src/entt/core/type_traits.hpp +++ b/src/entt/core/type_traits.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -747,8 +748,12 @@ inline constexpr bool is_transparent_v = is_transparent::value; * equality comparable, false otherwise. * @tparam Type The type to test. */ -template -struct is_equality_comparable: std::false_type {}; +template +struct is_equality_comparable; + +/*! @copydoc is_equality_comparable */ +template +struct is_equality_comparable: is_equality_comparable {}; /** * @cond TURN_OFF_DOXYGEN @@ -763,52 +768,56 @@ struct has_tuple_size_value: std::false_type {}; template struct has_tuple_size_value::value)>>: std::true_type {}; +template +struct has_value_type: std::false_type {}; + +template +struct has_value_type>: std::true_type {}; + template [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence) { return (is_equality_comparable>::value && ...); } template -[[nodiscard]] constexpr bool maybe_equality_comparable(choice_t<0>) { - return true; +[[nodiscard]] constexpr bool maybe_equality_comparable(char) { + return false; } template -[[nodiscard]] constexpr auto maybe_equality_comparable(choice_t<1>) -> decltype(std::declval(), bool{}) { - if constexpr(is_iterator_v) { - return true; - } else if constexpr(std::is_same_v) { - return maybe_equality_comparable(choice<0>); - } else { - return is_equality_comparable::value; - } -} - -template -[[nodiscard]] constexpr std::enable_if_t>>, bool> maybe_equality_comparable(choice_t<2>) { +[[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval() == std::declval()) { if constexpr(has_tuple_size_value::value) { return unpack_maybe_equality_comparable(std::make_index_sequence::value>{}); + } else if constexpr(has_value_type::value) { + if constexpr(is_iterator_v || std::is_same_v) { + return true; + } else { + return is_equality_comparable::value; + } } else { - return maybe_equality_comparable(choice<1>); + return true; } } } // namespace internal +template +struct is_equality_comparable: std::bool_constant(0)> {}; + /** * Internal details not to be documented. * @endcond */ -/*! @copydoc is_equality_comparable */ -template -struct is_equality_comparable() == std::declval())>> - : std::bool_constant(choice<2>)> {}; - /*! @copydoc is_equality_comparable */ template struct is_equality_comparable: std::false_type {}; +/*! @copydoc is_equality_comparable */ +template +// std::optional has a non sfinae-friendly comparison operator :( +struct is_equality_comparable>: is_equality_comparable::value_type> {}; + /** * @brief Helper variable template. * @tparam Type The type to test. diff --git a/test/entt/core/type_traits.cpp b/test/entt/core/type_traits.cpp index bc0149da2..838132ffd 100644 --- a/test/entt/core/type_traits.cpp +++ b/test/entt/core/type_traits.cpp @@ -212,6 +212,7 @@ TEST(IsEqualityComparable, Functionalities) { ASSERT_TRUE((entt::is_equality_comparable_v>)); ASSERT_TRUE((entt::is_equality_comparable_v>>)); ASSERT_TRUE(entt::is_equality_comparable_v::iterator>); + ASSERT_TRUE((entt::is_equality_comparable_v>)); ASSERT_TRUE(entt::is_equality_comparable_v); ASSERT_FALSE(entt::is_equality_comparable_v); @@ -223,6 +224,7 @@ TEST(IsEqualityComparable, Functionalities) { ASSERT_FALSE((entt::is_equality_comparable_v>>)); ASSERT_FALSE((entt::is_equality_comparable_v>)); ASSERT_FALSE((entt::is_equality_comparable_v>>)); + ASSERT_FALSE((entt::is_equality_comparable_v>)); ASSERT_FALSE(entt::is_equality_comparable_v); }