summaryrefslogtreecommitdiff
path: root/libcxx/include/__type_traits/is_equality_comparable.h
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/include/__type_traits/is_equality_comparable.h')
-rw-r--r--libcxx/include/__type_traits/is_equality_comparable.h30
1 files changed, 23 insertions, 7 deletions
diff --git a/libcxx/include/__type_traits/is_equality_comparable.h b/libcxx/include/__type_traits/is_equality_comparable.h
index b7a7cd219e30..381108365c00 100644
--- a/libcxx/include/__type_traits/is_equality_comparable.h
+++ b/libcxx/include/__type_traits/is_equality_comparable.h
@@ -15,6 +15,7 @@
#include <__type_traits/is_same.h>
#include <__type_traits/is_void.h>
#include <__type_traits/remove_cv.h>
+#include <__type_traits/remove_cvref.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
@@ -32,8 +33,9 @@ struct __is_equality_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>()
};
// A type is_trivially_equality_comparable if the expression `a == b` is equivalent to `std::memcmp(&a, &b, sizeof(T))`
-// (with `a` and `b` being of type `T`). There is no compiler built-in to check this, so we can only do this for known
-// types. In particular, these are the integral types and raw pointers.
+// (with `a` and `b` being of type `T`). For the case where we compare two object of the same type, we can use
+// __is_trivially_equality_comparable. We have special-casing for pointers which point to the same type ignoring
+// cv-qualifications and comparing to void-pointers.
//
// The following types are not trivially equality comparable:
// floating-point types: different bit-patterns can compare equal. (e.g 0.0 and -0.0)
@@ -43,20 +45,34 @@ struct __is_equality_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>()
// always compared.
template <class _Tp, class _Up>
-struct __libcpp_is_trivially_equality_comparable
- : integral_constant<bool,
- __is_equality_comparable<_Tp, _Up>::value && is_integral<_Tp>::value &&
- is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value> {};
+struct __libcpp_is_trivially_equality_comparable_impl : false_type {};
+
+template <class _Tp>
+struct __libcpp_is_trivially_equality_comparable_impl<_Tp, _Tp>
+#if __has_builtin(__is_trivially_equality_comparable)
+ : integral_constant<bool, __is_trivially_equality_comparable(_Tp) && __is_equality_comparable<_Tp, _Tp>::value> {
+};
+#else
+ : is_integral<_Tp> {
+};
+#endif // __has_builtin(__is_trivially_equality_comparable)
+
+template <class _Tp>
+struct __libcpp_is_trivially_equality_comparable_impl<_Tp*, _Tp*> : true_type {};
// TODO: Use is_pointer_inverconvertible_base_of
template <class _Tp, class _Up>
-struct __libcpp_is_trivially_equality_comparable<_Tp*, _Up*>
+struct __libcpp_is_trivially_equality_comparable_impl<_Tp*, _Up*>
: integral_constant<
bool,
__is_equality_comparable<_Tp*, _Up*>::value &&
(is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value || is_void<_Tp>::value || is_void<_Up>::value)> {
};
+template <class _Tp, class _Up>
+using __libcpp_is_trivially_equality_comparable =
+ __libcpp_is_trivially_equality_comparable_impl<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >;
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___TYPE_TRAITS_IS_EQUAILITY_COMPARABLE_H