1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 // template <class T1, class T2> struct pair
13 // template <class T1, class T2, class U1, class U2>
14 // constexpr common_comparison_category_t<synth-three-way-result<T1, U1>,synth-three-way-result<T2, U2>>
15 // operator<=>(const pair<T1,T2>&, const pair<U1,U2>&);
17 // UNSUPPORTED: c++03, c++11, c++14, c++17
22 #include <type_traits> // std::is_constant_evaluated
26 #include "test_macros.h"
29 concept HasEqual
= requires(T t
) { t
== t
; };
31 concept HasLess
= requires(T t
) { t
< t
; };
32 template <class T
, class U
= T
>
33 concept HasSpaceship
= requires(T t
, U u
) { t
<=> u
; };
35 constexpr bool test() {
37 // Pairs of different types should compare with strong ordering.
38 using P1
= std::pair
<int, int>;
39 using P2
= std::pair
<long long, long long>;
40 ASSERT_SAME_TYPE(decltype(P1() <=> P2()), std::strong_ordering
);
41 assert((P1(1, 1) <=> P2(1, 2)) == std::strong_ordering::less
);
42 assert((P1(2, 1) <=> P2(1, 2)) == std::strong_ordering::greater
);
43 assert((P1(0, 0) <=> P2(0, 0)) == std::strong_ordering::equal
);
46 // Pairs of different types should compare with partial ordering.
47 using P1
= std::pair
<int, int>;
48 using P2
= std::pair
<double, double>;
49 ASSERT_SAME_TYPE(decltype(P1() <=> P2()), std::partial_ordering
);
50 assert((P1(1, 1) <=> P2(1.0, 2.0)) == std::partial_ordering::less
);
51 assert((P1(2, 1) <=> P2(1.0, 2.0)) == std::partial_ordering::greater
);
52 assert((P1(0, 0) <=> P2(0.0, 0.0)) == std::partial_ordering::equivalent
);
54 { static_assert(!HasSpaceship
<std::pair
<int, int>, std::pair
<std::string
, int>>); }
56 // Pairs of types that both have strong ordering should compare with strong ordering.
57 using P
= std::pair
<int, int>;
58 ASSERT_SAME_TYPE(decltype(P() <=> P()), std::strong_ordering
);
59 assert((P(1, 1) <=> P(1, 2)) == std::strong_ordering::less
);
60 assert((P(2, 1) <=> P(1, 2)) == std::strong_ordering::greater
);
61 assert((P(0, 0) <=> P(0, 0)) == std::strong_ordering::equal
);
64 // Pairs of int and a type with no spaceship operator should compare with weak ordering.
67 constexpr bool operator==(const NoSpaceship
&) const = default;
68 constexpr bool operator<(const NoSpaceship
& other
) const { return value
< other
.value
; }
70 using P
= std::pair
<int, NoSpaceship
>;
71 ASSERT_SAME_TYPE(decltype(P() <=> P()), std::weak_ordering
);
72 assert((P(1, {1}) <=> P(1, {2})) == std::weak_ordering::less
);
73 assert((P(2, {1}) <=> P(1, {2})) == std::weak_ordering::greater
);
74 assert((P(0, {0}) <=> P(0, {0})) == std::weak_ordering::equivalent
);
77 // Pairs of int (strongly ordered) and double (partially ordered) should compare with partial ordering.
78 using P
= std::pair
<int, double>;
79 constexpr double nan
= std::numeric_limits
<double>::quiet_NaN();
80 ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering
);
81 assert((P(1, 1.0) <=> P(1, 2.0)) == std::partial_ordering::less
);
82 assert((P(1, 1.0) <=> P(1, 1.0)) == std::partial_ordering::equivalent
);
83 assert((P(1, -0.0) <=> P(1, 0.0)) == std::partial_ordering::equivalent
);
84 assert((P(1, 2.0) <=> P(1, 1.0)) == std::partial_ordering::greater
);
85 assert((P(1, nan
) <=> P(2, nan
)) == std::partial_ordering::less
);
86 assert((P(2, nan
) <=> P(1, nan
)) == std::partial_ordering::greater
);
87 assert((P(1, nan
) <=> P(1, nan
)) == std::partial_ordering::unordered
);
90 using P
= std::pair
<double, int>;
91 constexpr double nan
= std::numeric_limits
<double>::quiet_NaN();
92 ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering
);
93 assert((P(2.0, 1) <=> P(1.0, 2)) == std::partial_ordering::greater
);
94 assert((P(1.0, 1) <=> P(1.0, 2)) == std::partial_ordering::less
);
95 assert((P(nan
, 1) <=> P(nan
, 2)) == std::partial_ordering::unordered
);
99 constexpr bool operator==(const NoRelative
&) const;
101 static_assert(HasEqual
<std::pair
<int, NoRelative
>>);
102 static_assert(!HasLess
<std::pair
<int, NoRelative
>>);
103 static_assert(!HasSpaceship
<std::pair
<int, NoRelative
>>);
107 constexpr bool operator==(const NoLessThan
&) const;
108 constexpr bool operator>(const NoLessThan
&) const;
110 static_assert(HasEqual
<std::pair
<int, NoLessThan
>>);
111 static_assert(!HasLess
<std::pair
<int, NoLessThan
>>);
112 static_assert(!HasSpaceship
<std::pair
<int, NoLessThan
>>);
115 #ifdef TEST_COMPILER_GCC
116 // GCC cannot evaluate NaN @ non-NaN constexpr, so test that runtime-only.
117 if (!std::is_constant_evaluated())
121 using P
= std::pair
<int, double>;
122 constexpr double nan
= std::numeric_limits
<double>::quiet_NaN();
123 assert((P(1, 2.0) <=> P(1, nan
)) == std::partial_ordering::unordered
);
126 using P
= std::pair
<double, int>;
127 constexpr double nan
= std::numeric_limits
<double>::quiet_NaN();
128 assert((P(1.0, 1) <=> P(nan
, 2)) == std::partial_ordering::unordered
);
135 int main(int, char**) {
137 static_assert(test());