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
19template <class T, class U = T, typename Cat = std::partial_ordering>
20constexpr 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
46namespace fundamentals {
47static_assert(check_three_way_comparable_with<int, int>());
48static_assert(check_three_way_comparable_with<int, char>());
49static_assert(!check_three_way_comparable_with<int, unsigned int>());
50static_assert(check_three_way_comparable_with<int, double>());
51static_assert(check_three_way_comparable_with<int*, int*>());
52
53static_assert(check_three_way_comparable_with<int, int, std::strong_ordering>());
54static_assert(check_three_way_comparable_with<int, char, std::strong_ordering>());
55static_assert(check_three_way_comparable_with<int, short, std::strong_ordering>());
56
57static_assert(check_three_way_comparable_with<int, int, std::weak_ordering>());
58static_assert(check_three_way_comparable_with<int, char, std::weak_ordering>());
59static_assert(!check_three_way_comparable_with<int, unsigned int, std::weak_ordering>());
60
61static_assert(!check_three_way_comparable_with<int, bool>());
62static_assert(!check_three_way_comparable_with<int, int*>());
63static_assert(!check_three_way_comparable_with<int, int[5]>());
64static_assert(!check_three_way_comparable_with<int, int (*)()>());
65static_assert(!check_three_way_comparable_with<int, int (&)()>());
66struct S {};
67static_assert(!check_three_way_comparable_with<int, int S::*>());
68static_assert(!check_three_way_comparable_with<int, int (S::*)()>());
69static_assert(!check_three_way_comparable_with<int, int (S::*)() noexcept>());
70static_assert(!check_three_way_comparable_with<int, int (S::*)() const>());
71static_assert(!check_three_way_comparable_with<int, int (S::*)() const noexcept>());
72static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile>());
73static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile noexcept>());
74static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile>());
75static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile noexcept>());
76static_assert(!check_three_way_comparable_with<int, int (S::*)() &>());
77static_assert(!check_three_way_comparable_with<int, int (S::*)() & noexcept>());
78static_assert(!check_three_way_comparable_with<int, int (S::*)() const&>());
79static_assert(!check_three_way_comparable_with<int, int (S::*)() const & noexcept>());
80static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile&>());
81static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile & noexcept>());
82static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile&>());
83static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile & noexcept>());
84static_assert(!check_three_way_comparable_with<int, int (S::*)() &&>());
85static_assert(!check_three_way_comparable_with<int, int (S::*)() && noexcept>());
86static_assert(!check_three_way_comparable_with<int, int (S::*)() const&&>());
87static_assert(!check_three_way_comparable_with<int, int (S::*)() const&& noexcept>());
88static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile&&>());
89static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile&& noexcept>());
90static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile&&>());
91static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile&& noexcept>());
92static_assert(!check_three_way_comparable_with<int*, int[5]>());
93static_assert(!check_three_way_comparable_with<int[5], int[5]>());
94static_assert(!check_three_way_comparable_with<std::nullptr_t, int>());
95static_assert(!check_three_way_comparable_with<std::nullptr_t, int*>());
96static_assert(!check_three_way_comparable_with<std::nullptr_t, int[5]>());
97static_assert(!check_three_way_comparable_with<std::nullptr_t, int (*)()>());
98static_assert(!check_three_way_comparable_with<std::nullptr_t, int (&)()>());
99static_assert(!check_three_way_comparable_with<std::nullptr_t, int (S::*)()>());
100static_assert(!check_three_way_comparable_with<void, int>());
101static_assert(!check_three_way_comparable_with<void, int*>());
102static_assert(!check_three_way_comparable_with<void, std::nullptr_t>());
103static_assert(!check_three_way_comparable_with<void, int[5]>());
104static_assert(!check_three_way_comparable_with<void, int (*)()>());
105static_assert(!check_three_way_comparable_with<void, int (&)()>());
106static_assert(!check_three_way_comparable_with<void, int S::*>());
107static_assert(!check_three_way_comparable_with<void, int (S::*)()>());
108} // namespace fundamentals
109
110namespace user_defined {
111struct 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
120static_assert(check_three_way_comparable_with<S, int>());
121static_assert(check_three_way_comparable_with<S, int, std::strong_ordering>());
122static_assert(check_three_way_comparable_with<S, int, std::weak_ordering>());
123
124struct SpaceshipNotDeclared {
125};
126
127static_assert(!check_three_way_comparable_with<SpaceshipNotDeclared>());
128
129struct SpaceshipDeleted {
130 auto operator<=>(const SpaceshipDeleted&) const = delete;
131};
132
133static_assert(!check_three_way_comparable_with<SpaceshipDeleted>());
134
135struct SpaceshipWithoutEqualityOperator {
136 auto operator<=>(const SpaceshipWithoutEqualityOperator&) const;
137};
138
139static_assert(!check_three_way_comparable_with<SpaceshipWithoutEqualityOperator>());
140
141struct EqualityOperatorDeleted {
142 bool operator==(const EqualityOperatorDeleted&) const = delete;
143};
144
145static_assert(!check_three_way_comparable_with<EqualityOperatorDeleted>());
146
147struct EqualityOperatorOnly {
148 bool operator==(const EqualityOperatorOnly&) const = default;
149};
150
151static_assert(!check_three_way_comparable_with<EqualityOperatorOnly>());
152
153struct SpaceshipDeclaredEqualityOperatorDeleted {
154 bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete;
155 auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default;
156};
157
158static_assert(!check_three_way_comparable_with<SpaceshipDeclaredEqualityOperatorDeleted>());
159
160struct 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
168static_assert(!check_three_way_comparable_with<AllInequalityOperators>());
169
170struct 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
179static_assert(!check_three_way_comparable_with<AllComparisonOperators>());
180
181struct 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
188static_assert(!check_three_way_comparable_with<AllButOneInequalityOperators>());
189
190struct 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
198static_assert(!check_three_way_comparable_with<AllInequalityOperatorsOneDeleted>());
199
200struct EqualityOperatorWrongReturnType {
201 int operator==(const EqualityOperatorWrongReturnType&);
202 auto operator<=>(const EqualityOperatorWrongReturnType&) const = default;
203};
204
205static_assert(!check_three_way_comparable_with<EqualityOperatorWrongReturnType>());
206
207struct SpaceshipWrongReturnType {
208 bool operator==(const SpaceshipWrongReturnType&) const = default;
209 int operator<=>(const SpaceshipWrongReturnType&);
210};
211
212static_assert(!check_three_way_comparable_with<SpaceshipWrongReturnType>());
213
214struct EqualityOperatorNonConstArgument {
215 bool operator==(EqualityOperatorNonConstArgument&);
216 auto operator<=>(const EqualityOperatorNonConstArgument&) const = default;
217};
218
219static_assert(!check_three_way_comparable_with<EqualityOperatorNonConstArgument>());
220
221struct SpaceshipNonConstArgument {
222 bool operator==(const SpaceshipNonConstArgument&) const = default;
223 auto operator<=>(SpaceshipNonConstArgument&);
224};
225
226static_assert(!check_three_way_comparable_with<SpaceshipNonConstArgument>());
227} // namespace user_defined
228

source code of libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp