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