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