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 static_assert(std::three_way_comparable<char16_t volatile&>);
33 static_assert(std::three_way_comparable<char32_t const volatile&>);
34 #ifndef TEST_HAS_NO_INT128
35 static_assert(std::three_way_comparable<__int128_t const&>);
36 static_assert(std::three_way_comparable<__uint128_t const&>);
37 #endif
38 static_assert(std::three_way_comparable<unsigned char&&>);
39 static_assert(std::three_way_comparable<unsigned short const&&>);
40 static_assert(std::three_way_comparable<unsigned int volatile&&>);
41 static_assert(std::three_way_comparable<unsigned long const volatile&&>);
42 
43 // with explicit ordering
44 static_assert(std::three_way_comparable<int, std::strong_ordering>);
45 static_assert(std::three_way_comparable<int, std::weak_ordering>);
46 static_assert(std::three_way_comparable<double, std::partial_ordering>);
47 static_assert(!std::three_way_comparable<double, std::weak_ordering>);
48 static_assert(std::three_way_comparable<void*, std::strong_ordering>);
49 static_assert(std::three_way_comparable<void*, std::weak_ordering>);
50 static_assert(std::three_way_comparable<char*, std::strong_ordering>);
51 static_assert(std::three_way_comparable<char*, std::weak_ordering>);
52 static_assert(std::three_way_comparable<char const*, std::strong_ordering>);
53 static_assert(std::three_way_comparable<char const*, std::weak_ordering>);
54 static_assert(std::three_way_comparable<char volatile*, std::strong_ordering>);
55 static_assert(std::three_way_comparable<char volatile*, std::weak_ordering>);
56 static_assert(std::three_way_comparable<char const volatile*, std::strong_ordering>);
57 static_assert(std::three_way_comparable<char const volatile*, std::weak_ordering>);
58 static_assert(std::three_way_comparable<wchar_t&, std::strong_ordering>);
59 static_assert(std::three_way_comparable<wchar_t&, std::weak_ordering>);
60 static_assert(std::three_way_comparable<char8_t const&, std::strong_ordering>);
61 static_assert(std::three_way_comparable<char8_t const&, std::weak_ordering>);
62 static_assert(std::three_way_comparable<char16_t volatile&, std::strong_ordering>);
63 static_assert(std::three_way_comparable<char16_t volatile&, std::weak_ordering>);
64 static_assert(std::three_way_comparable<char32_t const volatile&, std::strong_ordering>);
65 static_assert(std::three_way_comparable<char32_t const volatile&, std::weak_ordering>);
66 static_assert(std::three_way_comparable<unsigned char&&, std::strong_ordering>);
67 static_assert(std::three_way_comparable<unsigned char&&, std::weak_ordering>);
68 static_assert(std::three_way_comparable<unsigned short const&&, std::strong_ordering>);
69 static_assert(std::three_way_comparable<unsigned short const&&, std::weak_ordering>);
70 static_assert(std::three_way_comparable<unsigned int volatile&&, std::strong_ordering>);
71 static_assert(std::three_way_comparable<unsigned int volatile&&, std::weak_ordering>);
72 static_assert(std::three_way_comparable<unsigned long const volatile&&, std::strong_ordering>);
73 static_assert(std::three_way_comparable<unsigned long const volatile&&, std::weak_ordering>);
74 
75 static_assert(!std::three_way_comparable<int[5]>);
76 static_assert(!std::three_way_comparable<int (*)(int)>);
77 static_assert(!std::three_way_comparable<int (&)(int)>);
78 static_assert(!std::three_way_comparable<int (*)(int) noexcept>);
79 static_assert(!std::three_way_comparable<int (&)(int) noexcept>);
80 static_assert(!std::three_way_comparable<std::nullptr_t>);
81 static_assert(!std::three_way_comparable<void>);
82 
83 struct S {};
84 static_assert(!std::three_way_comparable<int S::*>);
85 static_assert(!std::three_way_comparable<int (S::*)()>);
86 static_assert(!std::three_way_comparable<int (S::*)() noexcept>);
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::*)() const>);
92 static_assert(!std::three_way_comparable<int (S::*)() const 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::*)() volatile>);
98 static_assert(!std::three_way_comparable<int (S::*)() volatile 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::*)() const volatile>);
104 static_assert(!std::three_way_comparable<int (S::*)() const 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 } // namespace fundamentals
110 
111 namespace user_defined {
112 
113 struct S {
114     auto operator<=>(const S&) const = default;
115 };
116 
117 static_assert(std::three_way_comparable<S>);
118 static_assert(std::three_way_comparable<S, std::strong_ordering>);
119 static_assert(std::three_way_comparable<S, std::partial_ordering>);
120 
121 struct SpaceshipNotDeclared {
122 };
123 
124 static_assert(!std::three_way_comparable<SpaceshipNotDeclared>);
125 
126 struct SpaceshipDeleted {
127     auto operator<=>(const SpaceshipDeleted&) const = delete;
128 };
129 
130 static_assert(!std::three_way_comparable<SpaceshipDeleted>);
131 
132 struct SpaceshipWithoutEqualityOperator {
133     auto operator<=>(const SpaceshipWithoutEqualityOperator&) const;
134 };
135 
136 static_assert(!std::three_way_comparable<SpaceshipWithoutEqualityOperator>);
137 
138 struct EqualityOperatorDeleted {
139     bool operator==(const EqualityOperatorDeleted&) const = delete;
140 };
141 
142 static_assert(!std::three_way_comparable<EqualityOperatorDeleted>);
143 
144 struct EqualityOperatorOnly {
145     bool operator==(const EqualityOperatorOnly&) const = default;
146 };
147 
148 static_assert(!std::three_way_comparable<EqualityOperatorOnly>);
149 
150 struct SpaceshipDeclaredEqualityOperatorDeleted {
151     bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete;
152     auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default;
153 };
154 
155 static_assert(!std::three_way_comparable<SpaceshipDeclaredEqualityOperatorDeleted>);
156 
157 struct AllInequalityOperators {
158     bool operator<(const AllInequalityOperators&) const;
159     bool operator<=(const AllInequalityOperators&) const;
160     bool operator>(const AllInequalityOperators&) const;
161     bool operator>=(const AllInequalityOperators&) const;
162     bool operator!=(const AllInequalityOperators&) const;
163 };
164 
165 static_assert(!std::three_way_comparable<AllInequalityOperators>);
166 
167 struct AllComparisonOperators {
168     bool operator<(const AllComparisonOperators&) const;
169     bool operator<=(const AllComparisonOperators&) const;
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 };
175 
176 static_assert(!std::three_way_comparable<AllComparisonOperators>);
177 
178 struct AllButOneInequalityOperators {
179     bool operator<(const AllButOneInequalityOperators&) const;
180     bool operator<=(const AllButOneInequalityOperators&) const;
181     bool operator>(const AllButOneInequalityOperators&) const;
182     bool operator!=(const AllButOneInequalityOperators&) const;
183 };
184 
185 static_assert(!std::three_way_comparable<AllButOneInequalityOperators>);
186 
187 struct AllInequalityOperatorsOneDeleted {
188     bool operator<(const AllInequalityOperatorsOneDeleted&) const;
189     bool operator<=(const AllInequalityOperatorsOneDeleted&) const;
190     bool operator>(const AllInequalityOperatorsOneDeleted&) const;
191     bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete;
192     bool operator!=(const AllInequalityOperatorsOneDeleted&) const;
193 };
194 
195 static_assert(!std::three_way_comparable<AllInequalityOperatorsOneDeleted>);
196 
197 struct EqualityOperatorWrongReturnType {
198     int operator==(const EqualityOperatorWrongReturnType&);
199     auto operator<=>(const EqualityOperatorWrongReturnType&) const = default;
200 };
201 
202 static_assert(!std::three_way_comparable<EqualityOperatorWrongReturnType>);
203 
204 struct SpaceshipWrongReturnType {
205     bool operator==(const SpaceshipWrongReturnType&) const = default;
206     int operator<=>(const SpaceshipWrongReturnType&);
207 };
208 
209 static_assert(!std::three_way_comparable<SpaceshipWrongReturnType>);
210 
211 struct EqualityOperatorNonConstArgument {
212     bool operator==(EqualityOperatorNonConstArgument&);
213     auto operator<=>(const EqualityOperatorNonConstArgument&) const = default;
214 };
215 
216 static_assert(!std::three_way_comparable<EqualityOperatorNonConstArgument>);
217 
218 struct SpaceshipNonConstArgument {
219     bool operator==(const SpaceshipNonConstArgument&) const = default;
220     auto operator<=>(SpaceshipNonConstArgument&);
221 };
222 
223 static_assert(!std::three_way_comparable<SpaceshipNonConstArgument>);
224 } // namespace user_defined
225