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 #ifndef _LIBCPP___COMPARE_ORDERING_H
10 #define _LIBCPP___COMPARE_ORDERING_H
11 
12 #include <__config>
13 #include <type_traits>
14 
15 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16 #  pragma GCC system_header
17 #endif
18 
19 _LIBCPP_BEGIN_NAMESPACE_STD
20 
21 #if _LIBCPP_STD_VER > 17
22 
23 // exposition only
24 enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {
25   __less = -1,
26   __equiv = 0,
27   __greater = 1
28 };
29 
30 enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
31   __unordered = -127
32 };
33 
34 class partial_ordering;
35 class weak_ordering;
36 class strong_ordering;
37 
38 template<class _Tp, class... _Args>
39 inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...);
40 
41 struct _CmpUnspecifiedParam {
42   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL
43   _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
44 
45   template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>>
46   _CmpUnspecifiedParam(_Tp) = delete;
47 };
48 
49 class partial_ordering {
50   using _ValueT = signed char;
51 
52   _LIBCPP_HIDE_FROM_ABI
53   explicit constexpr partial_ordering(_OrdResult __v) noexcept
54       : __value_(_ValueT(__v)) {}
55 
56   _LIBCPP_HIDE_FROM_ABI
57   explicit constexpr partial_ordering(_NCmpResult __v) noexcept
58       : __value_(_ValueT(__v)) {}
59 
60   _LIBCPP_HIDE_FROM_ABI
61   constexpr bool __is_ordered() const noexcept {
62     return __value_ != _ValueT(_NCmpResult::__unordered);
63   }
64 public:
65   // valid values
66   static const partial_ordering less;
67   static const partial_ordering equivalent;
68   static const partial_ordering greater;
69   static const partial_ordering unordered;
70 
71   // comparisons
72   _LIBCPP_HIDE_FROM_ABI
73   friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
74 
75   _LIBCPP_HIDE_FROM_ABI
76   friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
77     return __v.__is_ordered() && __v.__value_ == 0;
78   }
79 
80   _LIBCPP_HIDE_FROM_ABI
81   friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
82     return __v.__is_ordered() && __v.__value_ < 0;
83   }
84 
85   _LIBCPP_HIDE_FROM_ABI
86   friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
87     return __v.__is_ordered() && __v.__value_ <= 0;
88   }
89 
90   _LIBCPP_HIDE_FROM_ABI
91   friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
92     return __v.__is_ordered() && __v.__value_ > 0;
93   }
94 
95   _LIBCPP_HIDE_FROM_ABI
96   friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
97     return __v.__is_ordered() && __v.__value_ >= 0;
98   }
99 
100   _LIBCPP_HIDE_FROM_ABI
101   friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
102     return __v.__is_ordered() && 0 < __v.__value_;
103   }
104 
105   _LIBCPP_HIDE_FROM_ABI
106   friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
107     return __v.__is_ordered() && 0 <= __v.__value_;
108   }
109 
110   _LIBCPP_HIDE_FROM_ABI
111   friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
112     return __v.__is_ordered() && 0 > __v.__value_;
113   }
114 
115   _LIBCPP_HIDE_FROM_ABI
116   friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
117     return __v.__is_ordered() && 0 >= __v.__value_;
118   }
119 
120   _LIBCPP_HIDE_FROM_ABI
121   friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
122     return __v;
123   }
124 
125   _LIBCPP_HIDE_FROM_ABI
126   friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
127     return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
128   }
129 private:
130   _ValueT __value_;
131 };
132 
133 inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
134 inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv);
135 inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
136 inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
137 
138 class weak_ordering {
139   using _ValueT = signed char;
140 
141   _LIBCPP_HIDE_FROM_ABI
142   explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
143 
144 public:
145   static const weak_ordering less;
146   static const weak_ordering equivalent;
147   static const weak_ordering greater;
148 
149   _LIBCPP_HIDE_FROM_ABI
150   constexpr operator partial_ordering() const noexcept {
151     return __value_ == 0 ? partial_ordering::equivalent
152         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
153   }
154 
155   // comparisons
156   _LIBCPP_HIDE_FROM_ABI
157   friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
158 
159   _LIBCPP_HIDE_FROM_ABI
160   friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
161     return __v.__value_ == 0;
162   }
163 
164   _LIBCPP_HIDE_FROM_ABI
165   friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
166     return __v.__value_ < 0;
167   }
168 
169   _LIBCPP_HIDE_FROM_ABI
170   friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
171     return __v.__value_ <= 0;
172   }
173 
174   _LIBCPP_HIDE_FROM_ABI
175   friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
176     return __v.__value_ > 0;
177   }
178 
179   _LIBCPP_HIDE_FROM_ABI
180   friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
181     return __v.__value_ >= 0;
182   }
183 
184   _LIBCPP_HIDE_FROM_ABI
185   friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
186     return 0 < __v.__value_;
187   }
188 
189   _LIBCPP_HIDE_FROM_ABI
190   friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
191     return 0 <= __v.__value_;
192   }
193 
194   _LIBCPP_HIDE_FROM_ABI
195   friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
196     return 0 > __v.__value_;
197   }
198 
199   _LIBCPP_HIDE_FROM_ABI
200   friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
201     return 0 >= __v.__value_;
202   }
203 
204   _LIBCPP_HIDE_FROM_ABI
205   friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
206     return __v;
207   }
208 
209   _LIBCPP_HIDE_FROM_ABI
210   friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
211     return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
212   }
213 
214 private:
215   _ValueT __value_;
216 };
217 
218 inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
219 inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv);
220 inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
221 
222 class strong_ordering {
223   using _ValueT = signed char;
224 
225   _LIBCPP_HIDE_FROM_ABI
226   explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
227 
228 public:
229   static const strong_ordering less;
230   static const strong_ordering equal;
231   static const strong_ordering equivalent;
232   static const strong_ordering greater;
233 
234   // conversions
235   _LIBCPP_HIDE_FROM_ABI
236   constexpr operator partial_ordering() const noexcept {
237     return __value_ == 0 ? partial_ordering::equivalent
238         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
239   }
240 
241   _LIBCPP_HIDE_FROM_ABI
242   constexpr operator weak_ordering() const noexcept {
243     return __value_ == 0 ? weak_ordering::equivalent
244         : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
245   }
246 
247   // comparisons
248   _LIBCPP_HIDE_FROM_ABI
249   friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
250 
251   _LIBCPP_HIDE_FROM_ABI
252   friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
253     return __v.__value_ == 0;
254   }
255 
256   _LIBCPP_HIDE_FROM_ABI
257   friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
258     return __v.__value_ < 0;
259   }
260 
261   _LIBCPP_HIDE_FROM_ABI
262   friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
263     return __v.__value_ <= 0;
264   }
265 
266   _LIBCPP_HIDE_FROM_ABI
267   friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
268     return __v.__value_ > 0;
269   }
270 
271   _LIBCPP_HIDE_FROM_ABI
272   friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
273     return __v.__value_ >= 0;
274   }
275 
276   _LIBCPP_HIDE_FROM_ABI
277   friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
278     return 0 < __v.__value_;
279   }
280 
281   _LIBCPP_HIDE_FROM_ABI
282   friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
283     return 0 <= __v.__value_;
284   }
285 
286   _LIBCPP_HIDE_FROM_ABI
287   friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
288     return 0 > __v.__value_;
289   }
290 
291   _LIBCPP_HIDE_FROM_ABI
292   friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
293     return 0 >= __v.__value_;
294   }
295 
296   _LIBCPP_HIDE_FROM_ABI
297   friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
298     return __v;
299   }
300 
301   _LIBCPP_HIDE_FROM_ABI
302   friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
303     return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
304   }
305 
306 private:
307   _ValueT __value_;
308 };
309 
310 inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
311 inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv);
312 inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv);
313 inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
314 
315 #endif // _LIBCPP_STD_VER > 17
316 
317 _LIBCPP_END_NAMESPACE_STD
318 
319 #endif // _LIBCPP___COMPARE_ORDERING_H
320