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 // template<class T, class Cat = partial_ordering>
12 // concept three_way_comparable = // see below
13 
14 #include <compare>
15 
16 #include "compare_types.h"
17 #include "test_macros.h"
18 
19 namespace fundamentals {
20 // with default ordering
21 static_assert(std::three_way_comparable<int>);
22 static_assert(std::three_way_comparable<double>);
23 static_assert(std::three_way_comparable<void*>);
24 static_assert(std::three_way_comparable<char*>);
25 static_assert(std::three_way_comparable<char const*>);
26 static_assert(std::three_way_comparable<char volatile*>);
27 static_assert(std::three_way_comparable<char const volatile*>);
28 static_assert(std::three_way_comparable<wchar_t&>);
29 #ifndef TEST_HAS_NO_CHAR8_T
30 static_assert(std::three_way_comparable<char8_t const&>);
31 #endif
32 #ifndef TEST_HAS_NO_UNICODE_CHARS
33 static_assert(std::three_way_comparable<char16_t volatile&>);
34 static_assert(std::three_way_comparable<char32_t const volatile&>);
35 #endif
36 #ifndef TEST_HAS_NO_INT128
37 static_assert(std::three_way_comparable<__int128_t const&>);
38 static_assert(std::three_way_comparable<__uint128_t const&>);
39 #endif
40 static_assert(std::three_way_comparable<unsigned char&&>);
41 static_assert(std::three_way_comparable<unsigned short const&&>);
42 static_assert(std::three_way_comparable<unsigned int volatile&&>);
43 static_assert(std::three_way_comparable<unsigned long const volatile&&>);
44 
45 // with explicit ordering
46 static_assert(std::three_way_comparable<int, std::strong_ordering>);
47 static_assert(std::three_way_comparable<int, std::weak_ordering>);
48 static_assert(std::three_way_comparable<double, std::partial_ordering>);
49 static_assert(!std::three_way_comparable<double, std::weak_ordering>);
50 static_assert(std::three_way_comparable<void*, std::strong_ordering>);
51 static_assert(std::three_way_comparable<void*, std::weak_ordering>);
52 static_assert(std::three_way_comparable<char*, std::strong_ordering>);
53 static_assert(std::three_way_comparable<char*, std::weak_ordering>);
54 static_assert(std::three_way_comparable<char const*, std::strong_ordering>);
55 static_assert(std::three_way_comparable<char const*, std::weak_ordering>);
56 static_assert(std::three_way_comparable<char volatile*, std::strong_ordering>);
57 static_assert(std::three_way_comparable<char volatile*, std::weak_ordering>);
58 static_assert(std::three_way_comparable<char const volatile*, std::strong_ordering>);
59 static_assert(std::three_way_comparable<char const volatile*, std::weak_ordering>);
60 static_assert(std::three_way_comparable<wchar_t&, std::strong_ordering>);
61 static_assert(std::three_way_comparable<wchar_t&, std::weak_ordering>);
62 static_assert(std::three_way_comparable<char8_t const&, std::strong_ordering>);
63 static_assert(std::three_way_comparable<char8_t const&, std::weak_ordering>);
64 static_assert(std::three_way_comparable<char16_t volatile&, std::strong_ordering>);
65 static_assert(std::three_way_comparable<char16_t volatile&, std::weak_ordering>);
66 static_assert(std::three_way_comparable<char32_t const volatile&, std::strong_ordering>);
67 static_assert(std::three_way_comparable<char32_t const volatile&, std::weak_ordering>);
68 static_assert(std::three_way_comparable<unsigned char&&, std::strong_ordering>);
69 static_assert(std::three_way_comparable<unsigned char&&, std::weak_ordering>);
70 static_assert(std::three_way_comparable<unsigned short const&&, std::strong_ordering>);
71 static_assert(std::three_way_comparable<unsigned short const&&, std::weak_ordering>);
72 static_assert(std::three_way_comparable<unsigned int volatile&&, std::strong_ordering>);
73 static_assert(std::three_way_comparable<unsigned int volatile&&, std::weak_ordering>);
74 static_assert(std::three_way_comparable<unsigned long const volatile&&, std::strong_ordering>);
75 static_assert(std::three_way_comparable<unsigned long const volatile&&, std::weak_ordering>);
76 
77 static_assert(!std::three_way_comparable<int[5]>);
78 static_assert(!std::three_way_comparable<int (*)(int)>);
79 static_assert(!std::three_way_comparable<int (&)(int)>);
80 static_assert(!std::three_way_comparable<int (*)(int) noexcept>);
81 static_assert(!std::three_way_comparable<int (&)(int) noexcept>);
82 static_assert(!std::three_way_comparable<std::nullptr_t>);
83 static_assert(!std::three_way_comparable<void>);
84 
85 struct S {};
86 static_assert(!std::three_way_comparable<int S::*>);
87 static_assert(!std::three_way_comparable<int (S::*)()>);
88 static_assert(!std::three_way_comparable<int (S::*)() noexcept>);
89 static_assert(!std::three_way_comparable<int (S::*)() &>);
90 static_assert(!std::three_way_comparable<int (S::*)() & noexcept>);
91 static_assert(!std::three_way_comparable<int (S::*)() &&>);
92 static_assert(!std::three_way_comparable<int (S::*)() && noexcept>);
93 static_assert(!std::three_way_comparable<int (S::*)() const>);
94 static_assert(!std::three_way_comparable<int (S::*)() const noexcept>);
95 static_assert(!std::three_way_comparable<int (S::*)() const&>);
96 static_assert(!std::three_way_comparable<int (S::*)() const & noexcept>);
97 static_assert(!std::three_way_comparable<int (S::*)() const&&>);
98 static_assert(!std::three_way_comparable<int (S::*)() const && noexcept>);
99 static_assert(!std::three_way_comparable<int (S::*)() volatile>);
100 static_assert(!std::three_way_comparable<int (S::*)() volatile noexcept>);
101 static_assert(!std::three_way_comparable<int (S::*)() volatile&>);
102 static_assert(!std::three_way_comparable<int (S::*)() volatile & noexcept>);
103 static_assert(!std::three_way_comparable<int (S::*)() volatile&&>);
104 static_assert(!std::three_way_comparable<int (S::*)() volatile && noexcept>);
105 static_assert(!std::three_way_comparable<int (S::*)() const volatile>);
106 static_assert(!std::three_way_comparable<int (S::*)() const volatile noexcept>);
107 static_assert(!std::three_way_comparable<int (S::*)() const volatile&>);
108 static_assert(!std::three_way_comparable<int (S::*)() const volatile & noexcept>);
109 static_assert(!std::three_way_comparable<int (S::*)() const volatile&&>);
110 static_assert(!std::three_way_comparable<int (S::*)() const volatile && noexcept>);
111 } // namespace fundamentals
112 
113 namespace user_defined {
114 
115 struct S {
116     auto operator<=>(const S&) const = default;
117 };
118 
119 static_assert(std::three_way_comparable<S>);
120 static_assert(std::three_way_comparable<S, std::strong_ordering>);
121 static_assert(std::three_way_comparable<S, std::partial_ordering>);
122 
123 struct SpaceshipNotDeclared {
124 };
125 
126 static_assert(!std::three_way_comparable<SpaceshipNotDeclared>);
127 
128 struct SpaceshipDeleted {
129     auto operator<=>(const SpaceshipDeleted&) const = delete;
130 };
131 
132 static_assert(!std::three_way_comparable<SpaceshipDeleted>);
133 
134 struct SpaceshipWithoutEqualityOperator {
135     auto operator<=>(const SpaceshipWithoutEqualityOperator&) const;
136 };
137 
138 static_assert(!std::three_way_comparable<SpaceshipWithoutEqualityOperator>);
139 
140 struct EqualityOperatorDeleted {
141     bool operator==(const EqualityOperatorDeleted&) const = delete;
142 };
143 
144 static_assert(!std::three_way_comparable<EqualityOperatorDeleted>);
145 
146 struct EqualityOperatorOnly {
147     bool operator==(const EqualityOperatorOnly&) const = default;
148 };
149 
150 static_assert(!std::three_way_comparable<EqualityOperatorOnly>);
151 
152 struct SpaceshipDeclaredEqualityOperatorDeleted {
153     bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete;
154     auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default;
155 };
156 
157 static_assert(!std::three_way_comparable<SpaceshipDeclaredEqualityOperatorDeleted>);
158 
159 struct AllInequalityOperators {
160     bool operator<(const AllInequalityOperators&) const;
161     bool operator<=(const AllInequalityOperators&) const;
162     bool operator>(const AllInequalityOperators&) const;
163     bool operator>=(const AllInequalityOperators&) const;
164     bool operator!=(const AllInequalityOperators&) const;
165 };
166 
167 static_assert(!std::three_way_comparable<AllInequalityOperators>);
168 
169 struct AllComparisonOperators {
170     bool operator<(const AllComparisonOperators&) const;
171     bool operator<=(const AllComparisonOperators&) const;
172     bool operator>(const AllComparisonOperators&) const;
173     bool operator>=(const AllComparisonOperators&) const;
174     bool operator!=(const AllComparisonOperators&) const;
175     bool operator==(const AllComparisonOperators&) const;
176 };
177 
178 static_assert(!std::three_way_comparable<AllComparisonOperators>);
179 
180 struct AllButOneInequalityOperators {
181     bool operator<(const AllButOneInequalityOperators&) const;
182     bool operator<=(const AllButOneInequalityOperators&) const;
183     bool operator>(const AllButOneInequalityOperators&) const;
184     bool operator!=(const AllButOneInequalityOperators&) const;
185 };
186 
187 static_assert(!std::three_way_comparable<AllButOneInequalityOperators>);
188 
189 struct AllInequalityOperatorsOneDeleted {
190     bool operator<(const AllInequalityOperatorsOneDeleted&) const;
191     bool operator<=(const AllInequalityOperatorsOneDeleted&) const;
192     bool operator>(const AllInequalityOperatorsOneDeleted&) const;
193     bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete;
194     bool operator!=(const AllInequalityOperatorsOneDeleted&) const;
195 };
196 
197 static_assert(!std::three_way_comparable<AllInequalityOperatorsOneDeleted>);
198 
199 struct EqualityOperatorWrongReturnType {
200     int operator==(const EqualityOperatorWrongReturnType&);
201     auto operator<=>(const EqualityOperatorWrongReturnType&) const = default;
202 };
203 
204 static_assert(!std::three_way_comparable<EqualityOperatorWrongReturnType>);
205 
206 struct SpaceshipWrongReturnType {
207     bool operator==(const SpaceshipWrongReturnType&) const = default;
208     int operator<=>(const SpaceshipWrongReturnType&);
209 };
210 
211 static_assert(!std::three_way_comparable<SpaceshipWrongReturnType>);
212 
213 struct EqualityOperatorNonConstArgument {
214     bool operator==(EqualityOperatorNonConstArgument&);
215     auto operator<=>(const EqualityOperatorNonConstArgument&) const = default;
216 };
217 
218 static_assert(!std::three_way_comparable<EqualityOperatorNonConstArgument>);
219 
220 struct SpaceshipNonConstArgument {
221     bool operator==(const SpaceshipNonConstArgument&) const = default;
222     auto operator<=>(SpaceshipNonConstArgument&);
223 };
224 
225 static_assert(!std::three_way_comparable<SpaceshipNonConstArgument>);
226 } // namespace user_defined
227