Skip to content

Commit acfd1b2

Browse files
committed
[libc++] Extend __default_three_way_comparator to any types that only implement operator<=>
1 parent 0a9b54b commit acfd1b2

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

libcxx/include/__utility/default_three_way_comparator.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2727
template <class _LHS, class _RHS, class = void>
2828
struct __default_three_way_comparator;
2929

30-
template <class _Tp>
31-
struct __default_three_way_comparator<_Tp, _Tp, __enable_if_t<is_arithmetic<_Tp>::value> > {
32-
_LIBCPP_HIDE_FROM_ABI static int operator()(_Tp __lhs, _Tp __rhs) {
30+
template <class _LHS, class _RHS>
31+
struct __default_three_way_comparator<_LHS,
32+
_RHS,
33+
__enable_if_t<is_arithmetic<_LHS>::value && is_arithmetic<_RHS>::value> > {
34+
_LIBCPP_HIDE_FROM_ABI static int operator()(_LHS __lhs, _RHS __rhs) {
3335
if (__lhs < __rhs)
3436
return -1;
3537
if (__lhs > __rhs)
@@ -38,6 +40,24 @@ struct __default_three_way_comparator<_Tp, _Tp, __enable_if_t<is_arithmetic<_Tp>
3840
}
3941
};
4042

43+
#if _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_lt_synthesises_from_spaceship)
44+
template <class _LHS, class _RHS>
45+
struct __default_three_way_comparator<
46+
_LHS,
47+
_RHS,
48+
__enable_if_t<(!is_arithmetic<_LHS>::value || !is_arithmetic<_RHS>::value) &&
49+
__builtin_lt_synthesises_from_spaceship(const _LHS&, const _RHS&)>> {
50+
_LIBCPP_HIDE_FROM_ABI static int operator()(const _LHS& __lhs, const _RHS& __rhs) {
51+
auto __res = __lhs <=> __rhs;
52+
if (__res < 0)
53+
return -1;
54+
if (__res > 0)
55+
return 1;
56+
return 0;
57+
}
58+
};
59+
#endif
60+
4161
template <class _LHS, class _RHS, bool = true>
4262
inline const bool __has_default_three_way_comparator_v = false;
4363

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
#include <__utility/default_three_way_comparator.h>
12+
#include <string>
13+
#include <vector>
14+
15+
static_assert(std::__has_default_three_way_comparator_v<int, int>);
16+
static_assert(std::__has_default_three_way_comparator_v<int, long>);
17+
static_assert(std::__has_default_three_way_comparator_v<long, int>);
18+
static_assert(std::__has_default_three_way_comparator_v<long, long>);
19+
static_assert(std::__has_default_three_way_comparator_v<const std::string&, const std::string&>);
20+
21+
#if __has_builtin(__builtin_lt_synthesises_from_spaceship)
22+
static_assert(std::__has_default_three_way_comparator_v<const std::string&, const std::string_view&>);
23+
static_assert(std::__has_default_three_way_comparator_v<const std::string&, const char*>);
24+
static_assert(!std::__has_default_three_way_comparator_v<const std::string&, const wchar_t*>);
25+
26+
static_assert(std::__has_default_three_way_comparator_v<const std::vector<int>&, const std::vector<int>&>);
27+
28+
struct MyStruct {
29+
int i;
30+
31+
friend auto operator<=>(MyStruct, MyStruct) = default;
32+
};
33+
34+
static_assert(std::__has_default_three_way_comparator_v<const MyStruct&, const MyStruct&>);
35+
#endif

0 commit comments

Comments
 (0)