[libcxx-commits] [libcxx] b25d36c - [libc++] Extend is_trivially_equality_comparable to integral types with the same signedness and size (#70344)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Nov 15 14:40:10 PST 2023


Author: philnik777
Date: 2023-11-15T23:40:05+01:00
New Revision: b25d36c3abae945788b881defc7eff4fdb46e3a2

URL: https://github.com/llvm/llvm-project/commit/b25d36c3abae945788b881defc7eff4fdb46e3a2
DIFF: https://github.com/llvm/llvm-project/commit/b25d36c3abae945788b881defc7eff4fdb46e3a2.diff

LOG: [libc++] Extend is_trivially_equality_comparable to integral types with the same signedness and size (#70344)

This enables all optimizations that rely on
`is_trivially_equality_comparable` to work with these integral types,
for example `std::equal` and `std::find`.

Added: 
    

Modified: 
    libcxx/include/__type_traits/is_equality_comparable.h
    libcxx/test/libcxx/type_traits/is_trivially_comparable.compile.pass.cpp
    libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__type_traits/is_equality_comparable.h b/libcxx/include/__type_traits/is_equality_comparable.h
index e8d3ce87961f148..00316ed637782d3 100644
--- a/libcxx/include/__type_traits/is_equality_comparable.h
+++ b/libcxx/include/__type_traits/is_equality_comparable.h
@@ -10,9 +10,11 @@
 #define _LIBCPP___TYPE_TRAITS_IS_EQUALITY_COMPARABLE_H
 
 #include <__config>
+#include <__type_traits/enable_if.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_integral.h>
 #include <__type_traits/is_same.h>
+#include <__type_traits/is_signed.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/remove_cv.h>
 #include <__type_traits/remove_cvref.h>
@@ -44,7 +46,7 @@ struct __is_equality_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>()
 //   but don't have the same bit-pattern. An exception to this is comparing to a void-pointer. There the bit-pattern is
 //   always compared.
 
-template <class _Tp, class _Up>
+template <class _Tp, class _Up, class = void>
 struct __libcpp_is_trivially_equality_comparable_impl : false_type {};
 
 template <class _Tp>
@@ -57,6 +59,13 @@ struct __libcpp_is_trivially_equality_comparable_impl<_Tp, _Tp>
 };
 #endif // __has_builtin(__is_trivially_equality_comparable)
 
+template <class _Tp, class _Up>
+struct __libcpp_is_trivially_equality_comparable_impl<
+    _Tp,
+    _Up,
+    __enable_if_t<is_integral<_Tp>::value && is_integral<_Up>::value && !is_same<_Tp, _Up>::value &&
+                  is_signed<_Tp>::value == is_signed<_Up>::value && sizeof(_Tp) == sizeof(_Up)> > : true_type {};
+
 template <class _Tp>
 struct __libcpp_is_trivially_equality_comparable_impl<_Tp*, _Tp*> : true_type {};
 

diff  --git a/libcxx/test/libcxx/type_traits/is_trivially_comparable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_trivially_comparable.compile.pass.cpp
index 3471415f4431166..e2be399456b1bc7 100644
--- a/libcxx/test/libcxx/type_traits/is_trivially_comparable.compile.pass.cpp
+++ b/libcxx/test/libcxx/type_traits/is_trivially_comparable.compile.pass.cpp
@@ -6,7 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <__type_traits/conditional.h>
 #include <__type_traits/is_equality_comparable.h>
+#include <__type_traits/is_signed.h>
+#include <cstdint>
 
 enum Enum : int {};
 enum class EnumClass : int {};
@@ -19,8 +22,8 @@ static_assert(std::__libcpp_is_trivially_equality_comparable<unsigned int, unsig
 static_assert(std::__libcpp_is_trivially_equality_comparable<const unsigned int, unsigned int>::value, "");
 static_assert(!std::__libcpp_is_trivially_equality_comparable<unsigned int, int>::value, "");
 
-static_assert(!std::__libcpp_is_trivially_equality_comparable<long, int>::value, "");
-static_assert(!std::__libcpp_is_trivially_equality_comparable<int, long>::value, "");
+static_assert(!std::__libcpp_is_trivially_equality_comparable<std::int32_t, std::int64_t>::value, "");
+static_assert(!std::__libcpp_is_trivially_equality_comparable<std::int64_t, std::int32_t>::value, "");
 
 static_assert(std::__libcpp_is_trivially_equality_comparable<int*, int*>::value, "");
 static_assert(std::__libcpp_is_trivially_equality_comparable<int*, void*>::value, "");
@@ -38,6 +41,12 @@ static_assert(!std::__libcpp_is_trivially_equality_comparable<float, float>::val
 static_assert(!std::__libcpp_is_trivially_equality_comparable<double, double>::value, "");
 static_assert(!std::__libcpp_is_trivially_equality_comparable<long double, long double>::value, "");
 
+static_assert(std::__libcpp_is_trivially_equality_comparable<
+                  char,
+                  typename std::conditional<std::is_signed<char>::value, signed char, unsigned char>::type>::value,
+              "");
+static_assert(std::__libcpp_is_trivially_equality_comparable<char16_t, std::uint_least16_t>::value, "");
+
 struct S {
   char c;
 };

diff  --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp
index 97cf59defc97c15..faf597c970ff23a 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp
@@ -18,6 +18,9 @@
 //   constexpr bool     // constexpr after c++17
 //   equal(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2);
 
+// We test the cartesian product, so we somethimes compare 
diff erently signed types
+// ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
+
 #include <algorithm>
 #include <cassert>
 #include <functional>
@@ -131,12 +134,30 @@ TEST_CONSTEXPR_CXX20 bool test() {
 struct Base {};
 struct Derived : virtual Base {};
 
+struct TestTypes {
+  template <class T>
+  struct Test {
+    template <class U>
+    void operator()() {
+      T a[] = {1, 2, 3, 4, 5, 6};
+      U b[] = {1, 2, 3, 4, 5, 6};
+      assert(std::equal(a, a + 6, b));
+    }
+  };
+
+  template <class T>
+  void operator()() {
+    types::for_each(types::integer_types(), Test<T>());
+  }
+};
+
 int main(int, char**) {
   test();
 #if TEST_STD_VER >= 20
   static_assert(test());
 #endif
 
+  types::for_each(types::integer_types(), TestTypes());
   types::for_each(types::as_pointers<types::cv_qualified_versions<int> >(),
                   TestIter2<int, types::as_pointers<types::cv_qualified_versions<int> > >());
   types::for_each(types::as_pointers<types::cv_qualified_versions<char> >(),


        


More information about the libcxx-commits mailing list