]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/libcxx/include/compare
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / libcxx / include / compare
1 // -*- C++ -*-
2 //===-------------------------- compare -----------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef _LIBCPP_COMPARE
11 #define _LIBCPP_COMPARE
12
13 /*
14     compare synopsis
15
16 namespace std {
17   // [cmp.categories], comparison category types
18   class weak_equality;
19   class strong_equality;
20   class partial_ordering;
21   class weak_ordering;
22   class strong_ordering;
23
24   // named comparison functions
25   constexpr bool is_eq  (weak_equality cmp) noexcept    { return cmp == 0; }
26   constexpr bool is_neq (weak_equality cmp) noexcept    { return cmp != 0; }
27   constexpr bool is_lt  (partial_ordering cmp) noexcept { return cmp < 0; }
28   constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; }
29   constexpr bool is_gt  (partial_ordering cmp) noexcept { return cmp > 0; }
30   constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; }
31
32   // [cmp.common], common comparison category type
33   template<class... Ts>
34   struct common_comparison_category {
35     using type = see below;
36   };
37   template<class... Ts>
38     using common_comparison_category_t = typename common_comparison_category<Ts...>::type;
39
40   // [cmp.alg], comparison algorithms
41   template<class T> constexpr strong_ordering strong_order(const T& a, const T& b);
42   template<class T> constexpr weak_ordering weak_order(const T& a, const T& b);
43   template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);
44   template<class T> constexpr strong_equality strong_equal(const T& a, const T& b);
45   template<class T> constexpr weak_equality weak_equal(const T& a, const T& b);
46 }
47 */
48
49 #include <__config>
50 #include <type_traits>
51 #include <array>
52
53 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
54 #pragma GCC system_header
55 #endif
56
57 _LIBCPP_BEGIN_NAMESPACE_STD
58
59 #if _LIBCPP_STD_VER > 17
60
61 // exposition only
62 enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char {
63   __zero = 0,
64   __equal = __zero,
65   __equiv = __equal,
66   __nonequal = 1,
67   __nonequiv = __nonequal
68 };
69
70 enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {
71   __less = -1,
72   __greater = 1
73 };
74
75 enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
76   __unordered = -127
77 };
78
79 struct _CmpUnspecifiedType;
80 using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
81
82 class  weak_equality {
83   _LIBCPP_INLINE_VISIBILITY
84   constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
85
86 public:
87   static const weak_equality equivalent;
88   static const weak_equality nonequivalent;
89
90   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
91   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
92   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
93   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
94
95 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
96   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
97   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
98 #endif
99
100 private:
101   _EqResult __value_;
102 };
103
104 _LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
105 _LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
106
107 _LIBCPP_INLINE_VISIBILITY
108 inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
109   return __v.__value_ == _EqResult::__zero;
110 }
111
112 _LIBCPP_INLINE_VISIBILITY
113 inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
114   return __v.__value_ == _EqResult::__zero;
115 }
116
117 _LIBCPP_INLINE_VISIBILITY
118 inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
119   return __v.__value_ != _EqResult::__zero;
120 }
121
122 _LIBCPP_INLINE_VISIBILITY
123 inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
124   return __v.__value_ != _EqResult::__zero;
125 }
126
127 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
128 _LIBCPP_INLINE_VISIBILITY
129 inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
130   return __v;
131 }
132
133 _LIBCPP_INLINE_VISIBILITY
134 inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
135   return __v;
136 }
137 #endif
138
139 class strong_equality {
140   _LIBCPP_INLINE_VISIBILITY
141   explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
142
143 public:
144   static const strong_equality equal;
145   static const strong_equality nonequal;
146   static const strong_equality equivalent;
147   static const strong_equality nonequivalent;
148
149   // conversion
150   _LIBCPP_INLINE_VISIBILITY constexpr operator weak_equality() const noexcept {
151     return __value_ == _EqResult::__zero ? weak_equality::equivalent
152           : weak_equality::nonequivalent;
153   }
154
155   // comparisons
156   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
157   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
158   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
159   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
160
161 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
162   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
163   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
164 #endif
165 private:
166   _EqResult __value_;
167 };
168
169 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equal(_EqResult::__equal);
170 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
171 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
172 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
173
174 _LIBCPP_INLINE_VISIBILITY
175 constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
176   return __v.__value_ == _EqResult::__zero;
177 }
178
179 _LIBCPP_INLINE_VISIBILITY
180 constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
181   return __v.__value_ == _EqResult::__zero;
182 }
183
184 _LIBCPP_INLINE_VISIBILITY
185 constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
186   return __v.__value_ != _EqResult::__zero;
187 }
188
189 _LIBCPP_INLINE_VISIBILITY
190 constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
191   return __v.__value_ != _EqResult::__zero;
192 }
193
194 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
195 _LIBCPP_INLINE_VISIBILITY
196 constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
197   return __v;
198 }
199
200 _LIBCPP_INLINE_VISIBILITY
201 constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
202   return __v;
203 }
204 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
205
206 class partial_ordering {
207   using _ValueT = signed char;
208
209   _LIBCPP_INLINE_VISIBILITY
210   explicit constexpr partial_ordering(_EqResult __v) noexcept
211       : __value_(_ValueT(__v)) {}
212
213   _LIBCPP_INLINE_VISIBILITY
214   explicit constexpr partial_ordering(_OrdResult __v) noexcept
215       : __value_(_ValueT(__v)) {}
216
217   _LIBCPP_INLINE_VISIBILITY
218   explicit constexpr partial_ordering(_NCmpResult __v) noexcept
219       : __value_(_ValueT(__v)) {}
220
221   constexpr bool __is_ordered() const noexcept {
222     return __value_ != _ValueT(_NCmpResult::__unordered);
223   }
224 public:
225   // valid values
226   static const partial_ordering less;
227   static const partial_ordering equivalent;
228   static const partial_ordering greater;
229   static const partial_ordering unordered;
230
231   // conversion
232   constexpr operator weak_equality() const noexcept {
233     return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
234   }
235
236   // comparisons
237   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
238   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
239   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept;
240   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
241   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept;
242   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
243   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
244   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
245   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept;
246   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
247   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept;
248   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
249
250 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
251   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
252   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
253 #endif
254
255 private:
256   _ValueT __value_;
257 };
258
259 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
260 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
261 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
262 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
263
264 _LIBCPP_INLINE_VISIBILITY
265 constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
266   return __v.__is_ordered() && __v.__value_ == 0;
267 }
268 _LIBCPP_INLINE_VISIBILITY
269 constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
270   return __v.__is_ordered() && __v.__value_ < 0;
271 }
272 _LIBCPP_INLINE_VISIBILITY
273 constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
274   return __v.__is_ordered() && __v.__value_ <= 0;
275 }
276 _LIBCPP_INLINE_VISIBILITY
277 constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
278   return __v.__is_ordered() && __v.__value_ > 0;
279 }
280 _LIBCPP_INLINE_VISIBILITY
281 constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
282   return __v.__is_ordered() && __v.__value_ >= 0;
283 }
284
285 _LIBCPP_INLINE_VISIBILITY
286 constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
287   return __v.__is_ordered() && 0 == __v.__value_;
288 }
289 _LIBCPP_INLINE_VISIBILITY
290 constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept {
291   return __v.__is_ordered() && 0 < __v.__value_;
292 }
293 _LIBCPP_INLINE_VISIBILITY
294 constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
295   return __v.__is_ordered() && 0 <= __v.__value_;
296 }
297 _LIBCPP_INLINE_VISIBILITY
298 constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept {
299   return __v.__is_ordered() && 0 > __v.__value_;
300 }
301 _LIBCPP_INLINE_VISIBILITY
302 constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
303   return __v.__is_ordered() && 0 >= __v.__value_;
304 }
305
306 _LIBCPP_INLINE_VISIBILITY
307 constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
308   return !__v.__is_ordered() || __v.__value_ != 0;
309 }
310 _LIBCPP_INLINE_VISIBILITY
311 constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
312   return !__v.__is_ordered() || __v.__value_ != 0;
313 }
314
315 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
316 _LIBCPP_INLINE_VISIBILITY
317 constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
318   return __v;
319 }
320 _LIBCPP_INLINE_VISIBILITY
321 constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
322   return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
323 }
324 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
325
326 class weak_ordering {
327   using _ValueT = signed char;
328
329   _LIBCPP_INLINE_VISIBILITY
330   explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
331   _LIBCPP_INLINE_VISIBILITY
332   explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
333
334 public:
335   static const weak_ordering less;
336   static const weak_ordering equivalent;
337   static const weak_ordering greater;
338
339   // conversions
340   _LIBCPP_INLINE_VISIBILITY
341   constexpr operator weak_equality() const noexcept {
342     return __value_ == 0 ? weak_equality::equivalent
343                          : weak_equality::nonequivalent;
344   }
345
346   _LIBCPP_INLINE_VISIBILITY
347   constexpr operator partial_ordering() const noexcept {
348     return __value_ == 0 ? partial_ordering::equivalent
349         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
350   }
351
352   // comparisons
353   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
354   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
355   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept;
356   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
357   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept;
358   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
359   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
360   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
361   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept;
362   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
363   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept;
364   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
365
366 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
367   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
368   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
369 #endif
370
371 private:
372   _ValueT __value_;
373 };
374
375 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
376 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
377 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
378
379 _LIBCPP_INLINE_VISIBILITY
380 constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
381   return __v.__value_ == 0;
382 }
383 _LIBCPP_INLINE_VISIBILITY
384 constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
385   return __v.__value_ != 0;
386 }
387 _LIBCPP_INLINE_VISIBILITY
388 constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
389   return __v.__value_ < 0;
390 }
391 _LIBCPP_INLINE_VISIBILITY
392 constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
393   return __v.__value_ <= 0;
394 }
395 _LIBCPP_INLINE_VISIBILITY
396 constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
397   return __v.__value_ > 0;
398 }
399 _LIBCPP_INLINE_VISIBILITY
400 constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
401   return __v.__value_ >= 0;
402 }
403 _LIBCPP_INLINE_VISIBILITY
404 constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
405   return 0 == __v.__value_;
406 }
407 _LIBCPP_INLINE_VISIBILITY
408 constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
409   return 0 != __v.__value_;
410 }
411 _LIBCPP_INLINE_VISIBILITY
412 constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
413   return 0 < __v.__value_;
414 }
415 _LIBCPP_INLINE_VISIBILITY
416 constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
417   return 0 <= __v.__value_;
418 }
419 _LIBCPP_INLINE_VISIBILITY
420 constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
421   return 0 > __v.__value_;
422 }
423 _LIBCPP_INLINE_VISIBILITY
424 constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
425   return 0 >= __v.__value_;
426 }
427
428 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
429 _LIBCPP_INLINE_VISIBILITY
430 constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
431   return __v;
432 }
433 _LIBCPP_INLINE_VISIBILITY
434 constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
435   return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
436 }
437 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
438
439 class strong_ordering {
440   using _ValueT = signed char;
441
442   _LIBCPP_INLINE_VISIBILITY
443   explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
444   _LIBCPP_INLINE_VISIBILITY
445   explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
446
447 public:
448   static const strong_ordering less;
449   static const strong_ordering equal;
450   static const strong_ordering equivalent;
451   static const strong_ordering greater;
452
453   // conversions
454   _LIBCPP_INLINE_VISIBILITY
455   constexpr operator weak_equality() const noexcept {
456     return __value_ == 0 ? weak_equality::equivalent
457                          : weak_equality::nonequivalent;
458   }
459
460   _LIBCPP_INLINE_VISIBILITY
461   constexpr operator strong_equality() const noexcept {
462     return __value_ == 0 ? strong_equality::equal
463                          : strong_equality::nonequal;
464   }
465
466   _LIBCPP_INLINE_VISIBILITY
467   constexpr operator partial_ordering() const noexcept {
468     return __value_ == 0 ? partial_ordering::equivalent
469         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
470   }
471
472   _LIBCPP_INLINE_VISIBILITY
473   constexpr operator weak_ordering() const noexcept {
474     return __value_ == 0 ? weak_ordering::equivalent
475         : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
476   }
477
478   // comparisons
479   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
480   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
481   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept;
482   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
483   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept;
484   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
485   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
486   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
487   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept;
488   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
489   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept;
490   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
491
492 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
493   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
494   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
495 #endif
496
497 private:
498   _ValueT __value_;
499 };
500
501 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
502 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
503 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
504 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
505
506 _LIBCPP_INLINE_VISIBILITY
507 constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
508   return __v.__value_ == 0;
509 }
510 _LIBCPP_INLINE_VISIBILITY
511 constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
512   return __v.__value_ != 0;
513 }
514 _LIBCPP_INLINE_VISIBILITY
515 constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
516   return __v.__value_ < 0;
517 }
518 _LIBCPP_INLINE_VISIBILITY
519 constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
520   return __v.__value_ <= 0;
521 }
522 _LIBCPP_INLINE_VISIBILITY
523 constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
524   return __v.__value_ > 0;
525 }
526 _LIBCPP_INLINE_VISIBILITY
527 constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
528   return __v.__value_ >= 0;
529 }
530 _LIBCPP_INLINE_VISIBILITY
531 constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
532   return 0 == __v.__value_;
533 }
534 _LIBCPP_INLINE_VISIBILITY
535 constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
536   return 0 != __v.__value_;
537 }
538 _LIBCPP_INLINE_VISIBILITY
539 constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
540   return 0 < __v.__value_;
541 }
542 _LIBCPP_INLINE_VISIBILITY
543 constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
544   return 0 <= __v.__value_;
545 }
546 _LIBCPP_INLINE_VISIBILITY
547 constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
548   return 0 > __v.__value_;
549 }
550 _LIBCPP_INLINE_VISIBILITY
551 constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
552   return 0 >= __v.__value_;
553 }
554
555 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
556 _LIBCPP_INLINE_VISIBILITY
557 constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
558   return __v;
559 }
560 _LIBCPP_INLINE_VISIBILITY
561 constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
562   return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
563 }
564 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
565
566 // named comparison functions
567 _LIBCPP_INLINE_VISIBILITY
568 constexpr bool is_eq(weak_equality __cmp) noexcept    { return __cmp == 0; }
569
570 _LIBCPP_INLINE_VISIBILITY
571 constexpr bool is_neq(weak_equality __cmp) noexcept    { return __cmp != 0; }
572
573 _LIBCPP_INLINE_VISIBILITY
574 constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
575
576 _LIBCPP_INLINE_VISIBILITY
577 constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
578
579 _LIBCPP_INLINE_VISIBILITY
580 constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
581
582 _LIBCPP_INLINE_VISIBILITY
583 constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
584
585 namespace __comp_detail {
586
587 enum _ClassifyCompCategory : unsigned{
588   _None,
589   _WeakEq,
590   _StrongEq,
591   _PartialOrd,
592   _WeakOrd,
593   _StrongOrd,
594   _CCC_Size
595 };
596
597 template <class _Tp>
598 _LIBCPP_INLINE_VISIBILITY
599 constexpr _ClassifyCompCategory __type_to_enum() noexcept {
600   if (is_same_v<_Tp, weak_equality>)
601     return _WeakEq;
602   if (is_same_v<_Tp, strong_equality>)
603     return _StrongEq;
604   if (is_same_v<_Tp, partial_ordering>)
605     return _PartialOrd;
606   if (is_same_v<_Tp, weak_ordering>)
607     return _WeakOrd;
608   if (is_same_v<_Tp, strong_ordering>)
609     return _StrongOrd;
610   return _None;
611 }
612
613 template <size_t _Size>
614 constexpr _ClassifyCompCategory
615 __compute_comp_type(std::array<_ClassifyCompCategory, _Size> __types) {
616   std::array<int, _CCC_Size> __seen = {};
617   for (auto __type : __types)
618     ++__seen[__type];
619   if (__seen[_None])
620     return _None;
621   if (__seen[_WeakEq])
622     return _WeakEq;
623   if (__seen[_StrongEq] && (__seen[_PartialOrd] || __seen[_WeakOrd]))
624     return _WeakEq;
625   if (__seen[_StrongEq])
626     return _StrongEq;
627   if (__seen[_PartialOrd])
628     return _PartialOrd;
629   if (__seen[_WeakOrd])
630     return _WeakOrd;
631   return _StrongOrd;
632 }
633
634 template <class ..._Ts>
635 constexpr auto __get_comp_type() {
636   using _CCC = _ClassifyCompCategory;
637   constexpr array<_CCC, sizeof...(_Ts)> __type_kinds{{__comp_detail::__type_to_enum<_Ts>()...}};
638   constexpr _CCC _Cat = sizeof...(_Ts) == 0 ? _StrongOrd
639       : __compute_comp_type(__type_kinds);
640   if constexpr (_Cat == _None)
641     return void();
642   else if constexpr (_Cat == _WeakEq)
643     return weak_equality::equivalent;
644   else if constexpr (_Cat == _StrongEq)
645     return strong_equality::equivalent;
646   else if constexpr (_Cat == _PartialOrd)
647     return partial_ordering::equivalent;
648   else if constexpr (_Cat == _WeakOrd)
649     return weak_ordering::equivalent;
650   else if constexpr (_Cat == _StrongOrd)
651     return strong_ordering::equivalent;
652   else
653     static_assert(_Cat != _Cat, "unhandled case");
654 }
655 } // namespace __comp_detail
656
657 // [cmp.common], common comparison category type
658 template<class... _Ts>
659 struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
660   using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
661 };
662
663 template<class... _Ts>
664 using common_comparison_category_t = typename common_comparison_category<_Ts...>::type;
665
666 // [cmp.alg], comparison algorithms
667 // TODO: unimplemented
668 template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs);
669 template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs);
670 template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs);
671 template<class _Tp> constexpr strong_equality strong_equal(const _Tp& __lhs, const _Tp& __rhs);
672 template<class _Tp> constexpr weak_equality weak_equal(const _Tp& __lhs, const _Tp& __rhs);
673
674 #endif // _LIBCPP_STD_VER > 17
675
676 _LIBCPP_END_NAMESPACE_STD
677
678 #endif // _LIBCPP_COMPARE