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