Skip to content

Commit b25d36c

Browse files
authored
[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`.
1 parent eaff083 commit b25d36c

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

libcxx/include/__type_traits/is_equality_comparable.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
#define _LIBCPP___TYPE_TRAITS_IS_EQUALITY_COMPARABLE_H
1111

1212
#include <__config>
13+
#include <__type_traits/enable_if.h>
1314
#include <__type_traits/integral_constant.h>
1415
#include <__type_traits/is_integral.h>
1516
#include <__type_traits/is_same.h>
17+
#include <__type_traits/is_signed.h>
1618
#include <__type_traits/is_void.h>
1719
#include <__type_traits/remove_cv.h>
1820
#include <__type_traits/remove_cvref.h>
@@ -44,7 +46,7 @@ struct __is_equality_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>()
4446
// but don't have the same bit-pattern. An exception to this is comparing to a void-pointer. There the bit-pattern is
4547
// always compared.
4648

47-
template <class _Tp, class _Up>
49+
template <class _Tp, class _Up, class = void>
4850
struct __libcpp_is_trivially_equality_comparable_impl : false_type {};
4951

5052
template <class _Tp>
@@ -57,6 +59,13 @@ struct __libcpp_is_trivially_equality_comparable_impl<_Tp, _Tp>
5759
};
5860
#endif // __has_builtin(__is_trivially_equality_comparable)
5961

62+
template <class _Tp, class _Up>
63+
struct __libcpp_is_trivially_equality_comparable_impl<
64+
_Tp,
65+
_Up,
66+
__enable_if_t<is_integral<_Tp>::value && is_integral<_Up>::value && !is_same<_Tp, _Up>::value &&
67+
is_signed<_Tp>::value == is_signed<_Up>::value && sizeof(_Tp) == sizeof(_Up)> > : true_type {};
68+
6069
template <class _Tp>
6170
struct __libcpp_is_trivially_equality_comparable_impl<_Tp*, _Tp*> : true_type {};
6271

libcxx/test/libcxx/type_traits/is_trivially_comparable.compile.pass.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include <__type_traits/conditional.h>
910
#include <__type_traits/is_equality_comparable.h>
11+
#include <__type_traits/is_signed.h>
12+
#include <cstdint>
1013

1114
enum Enum : int {};
1215
enum class EnumClass : int {};
@@ -19,8 +22,8 @@ static_assert(std::__libcpp_is_trivially_equality_comparable<unsigned int, unsig
1922
static_assert(std::__libcpp_is_trivially_equality_comparable<const unsigned int, unsigned int>::value, "");
2023
static_assert(!std::__libcpp_is_trivially_equality_comparable<unsigned int, int>::value, "");
2124

22-
static_assert(!std::__libcpp_is_trivially_equality_comparable<long, int>::value, "");
23-
static_assert(!std::__libcpp_is_trivially_equality_comparable<int, long>::value, "");
25+
static_assert(!std::__libcpp_is_trivially_equality_comparable<std::int32_t, std::int64_t>::value, "");
26+
static_assert(!std::__libcpp_is_trivially_equality_comparable<std::int64_t, std::int32_t>::value, "");
2427

2528
static_assert(std::__libcpp_is_trivially_equality_comparable<int*, int*>::value, "");
2629
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
3841
static_assert(!std::__libcpp_is_trivially_equality_comparable<double, double>::value, "");
3942
static_assert(!std::__libcpp_is_trivially_equality_comparable<long double, long double>::value, "");
4043

44+
static_assert(std::__libcpp_is_trivially_equality_comparable<
45+
char,
46+
typename std::conditional<std::is_signed<char>::value, signed char, unsigned char>::type>::value,
47+
"");
48+
static_assert(std::__libcpp_is_trivially_equality_comparable<char16_t, std::uint_least16_t>::value, "");
49+
4150
struct S {
4251
char c;
4352
};

libcxx/test/std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
// constexpr bool // constexpr after c++17
1919
// equal(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2);
2020

21+
// We test the cartesian product, so we somethimes compare differently signed types
22+
// ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
23+
2124
#include <algorithm>
2225
#include <cassert>
2326
#include <functional>
@@ -131,12 +134,30 @@ TEST_CONSTEXPR_CXX20 bool test() {
131134
struct Base {};
132135
struct Derived : virtual Base {};
133136

137+
struct TestTypes {
138+
template <class T>
139+
struct Test {
140+
template <class U>
141+
void operator()() {
142+
T a[] = {1, 2, 3, 4, 5, 6};
143+
U b[] = {1, 2, 3, 4, 5, 6};
144+
assert(std::equal(a, a + 6, b));
145+
}
146+
};
147+
148+
template <class T>
149+
void operator()() {
150+
types::for_each(types::integer_types(), Test<T>());
151+
}
152+
};
153+
134154
int main(int, char**) {
135155
test();
136156
#if TEST_STD_VER >= 20
137157
static_assert(test());
138158
#endif
139159

160+
types::for_each(types::integer_types(), TestTypes());
140161
types::for_each(types::as_pointers<types::cv_qualified_versions<int> >(),
141162
TestIter2<int, types::as_pointers<types::cv_qualified_versions<int> > >());
142163
types::for_each(types::as_pointers<types::cv_qualified_versions<char> >(),

0 commit comments

Comments
 (0)