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 _CmpUnspecifiedType;
158using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
159
160class  weak_equality {
161  _LIBCPP_INLINE_VISIBILITY
162  constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
163
164public:
165  static const weak_equality equivalent;
166  static const weak_equality nonequivalent;
167
168  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
169  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
170  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
171  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
172
173#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
174  _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
175  _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
176#endif
177
178private:
179  _EqResult __value_;
180};
181
182_LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
183_LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
184
185_LIBCPP_INLINE_VISIBILITY
186inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
187  return __v.__value_ == _EqResult::__zero;
188}
189
190_LIBCPP_INLINE_VISIBILITY
191inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
192  return __v.__value_ == _EqResult::__zero;
193}
194
195_LIBCPP_INLINE_VISIBILITY
196inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
197  return __v.__value_ != _EqResult::__zero;
198}
199
200_LIBCPP_INLINE_VISIBILITY
201inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
202  return __v.__value_ != _EqResult::__zero;
203}
204
205#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
206_LIBCPP_INLINE_VISIBILITY
207inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
208  return __v;
209}
210
211_LIBCPP_INLINE_VISIBILITY
212inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
213  return __v;
214}
215#endif
216
217class strong_equality {
218  _LIBCPP_INLINE_VISIBILITY
219  explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
220
221public:
222  static const strong_equality equal;
223  static const strong_equality nonequal;
224  static const strong_equality equivalent;
225  static const strong_equality nonequivalent;
226
227  // conversion
228  _LIBCPP_INLINE_VISIBILITY constexpr operator weak_equality() const noexcept {
229    return __value_ == _EqResult::__zero ? weak_equality::equivalent
230          : weak_equality::nonequivalent;
231  }
232
233  // comparisons
234  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
235  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
236  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
237  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
238
239#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
240  _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
241  _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
242#endif
243private:
244  _EqResult __value_;
245};
246
247_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equal(_EqResult::__equal);
248_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
249_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
250_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
251
252_LIBCPP_INLINE_VISIBILITY
253constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
254  return __v.__value_ == _EqResult::__zero;
255}
256
257_LIBCPP_INLINE_VISIBILITY
258constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
259  return __v.__value_ == _EqResult::__zero;
260}
261
262_LIBCPP_INLINE_VISIBILITY
263constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
264  return __v.__value_ != _EqResult::__zero;
265}
266
267_LIBCPP_INLINE_VISIBILITY
268constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
269  return __v.__value_ != _EqResult::__zero;
270}
271
272#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
273_LIBCPP_INLINE_VISIBILITY
274constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
275  return __v;
276}
277
278_LIBCPP_INLINE_VISIBILITY
279constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
280  return __v;
281}
282#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
283
284class partial_ordering {
285  using _ValueT = signed char;
286
287  _LIBCPP_INLINE_VISIBILITY
288  explicit constexpr partial_ordering(_EqResult __v) noexcept
289      : __value_(_ValueT(__v)) {}
290
291  _LIBCPP_INLINE_VISIBILITY
292  explicit constexpr partial_ordering(_OrdResult __v) noexcept
293      : __value_(_ValueT(__v)) {}
294
295  _LIBCPP_INLINE_VISIBILITY
296  explicit constexpr partial_ordering(_NCmpResult __v) noexcept
297      : __value_(_ValueT(__v)) {}
298
299  constexpr bool __is_ordered() const noexcept {
300    return __value_ != _ValueT(_NCmpResult::__unordered);
301  }
302public:
303  // valid values
304  static const partial_ordering less;
305  static const partial_ordering equivalent;
306  static const partial_ordering greater;
307  static const partial_ordering unordered;
308
309  // conversion
310  constexpr operator weak_equality() const noexcept {
311    return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
312  }
313
314  // comparisons
315  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
316  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
317  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept;
318  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
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==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
322  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
323  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept;
324  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) 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
328#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
329  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
330
331  _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
332  _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
333#endif
334
335private:
336  _ValueT __value_;
337};
338
339_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
340_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
341_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
342_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
343
344_LIBCPP_INLINE_VISIBILITY
345constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
346  return __v.__is_ordered() && __v.__value_ == 0;
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
365_LIBCPP_INLINE_VISIBILITY
366constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
367  return __v.__is_ordered() && 0 == __v.__value_;
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
386_LIBCPP_INLINE_VISIBILITY
387constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
388  return !__v.__is_ordered() || __v.__value_ != 0;
389}
390_LIBCPP_INLINE_VISIBILITY
391constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
392  return !__v.__is_ordered() || __v.__value_ != 0;
393}
394
395#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
396_LIBCPP_INLINE_VISIBILITY
397constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
398  return __v;
399}
400_LIBCPP_INLINE_VISIBILITY
401constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
402  return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
403}
404#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
405
406class weak_ordering {
407  using _ValueT = signed char;
408
409  _LIBCPP_INLINE_VISIBILITY
410  explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
411  _LIBCPP_INLINE_VISIBILITY
412  explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
413
414public:
415  static const weak_ordering less;
416  static const weak_ordering equivalent;
417  static const weak_ordering greater;
418
419  // conversions
420  _LIBCPP_INLINE_VISIBILITY
421  constexpr operator weak_equality() const noexcept {
422    return __value_ == 0 ? weak_equality::equivalent
423                         : weak_equality::nonequivalent;
424  }
425
426  _LIBCPP_INLINE_VISIBILITY
427  constexpr operator partial_ordering() const noexcept {
428    return __value_ == 0 ? partial_ordering::equivalent
429        : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
430  }
431
432  // comparisons
433  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
434  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
435  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept;
436  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
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==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
440  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
441  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept;
442  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) 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
446#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
447  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
448
449  _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
450  _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
451#endif
452
453private:
454  _ValueT __value_;
455};
456
457_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
458_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
459_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
460
461_LIBCPP_INLINE_VISIBILITY
462constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
463  return __v.__value_ == 0;
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==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
487  return 0 == __v.__value_;
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
510#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
511_LIBCPP_INLINE_VISIBILITY
512constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
513  return __v;
514}
515_LIBCPP_INLINE_VISIBILITY
516constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
517  return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
518}
519#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
520
521class strong_ordering {
522  using _ValueT = signed char;
523
524  _LIBCPP_INLINE_VISIBILITY
525  explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
526  _LIBCPP_INLINE_VISIBILITY
527  explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
528
529public:
530  static const strong_ordering less;
531  static const strong_ordering equal;
532  static const strong_ordering equivalent;
533  static const strong_ordering greater;
534
535  // conversions
536  _LIBCPP_INLINE_VISIBILITY
537  constexpr operator weak_equality() const noexcept {
538    return __value_ == 0 ? weak_equality::equivalent
539                         : weak_equality::nonequivalent;
540  }
541
542  _LIBCPP_INLINE_VISIBILITY
543  constexpr operator strong_equality() const noexcept {
544    return __value_ == 0 ? strong_equality::equal
545                         : strong_equality::nonequal;
546  }
547
548  _LIBCPP_INLINE_VISIBILITY
549  constexpr operator partial_ordering() const noexcept {
550    return __value_ == 0 ? partial_ordering::equivalent
551        : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
552  }
553
554  _LIBCPP_INLINE_VISIBILITY
555  constexpr operator weak_ordering() const noexcept {
556    return __value_ == 0 ? weak_ordering::equivalent
557        : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
558  }
559
560  // comparisons
561  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
562  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
563  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept;
564  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
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==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
568  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
569  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept;
570  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) 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
574#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
575  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
576
577  _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
578  _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
579#endif
580
581private:
582  _ValueT __value_;
583};
584
585_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
586_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
587_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
588_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
589
590_LIBCPP_INLINE_VISIBILITY
591constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
592  return __v.__value_ == 0;
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==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
616  return 0 == __v.__value_;
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
639#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
640_LIBCPP_INLINE_VISIBILITY
641constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
642  return __v;
643}
644_LIBCPP_INLINE_VISIBILITY
645constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
646  return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
647}
648#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
649
650// named comparison functions
651_LIBCPP_INLINE_VISIBILITY
652constexpr bool is_eq(weak_equality __cmp) noexcept    { return __cmp == 0; }
653
654_LIBCPP_INLINE_VISIBILITY
655constexpr bool is_neq(weak_equality __cmp) noexcept    { return __cmp != 0; }
656
657_LIBCPP_INLINE_VISIBILITY
658constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
659
660_LIBCPP_INLINE_VISIBILITY
661constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
662
663_LIBCPP_INLINE_VISIBILITY
664constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
665
666_LIBCPP_INLINE_VISIBILITY
667constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
668
669namespace __comp_detail {
670
671enum _ClassifyCompCategory : unsigned{
672  _None,
673  _WeakEq,
674  _StrongEq,
675  _PartialOrd,
676  _WeakOrd,
677  _StrongOrd,
678  _CCC_Size
679};
680
681template <class _Tp>
682_LIBCPP_INLINE_VISIBILITY
683constexpr _ClassifyCompCategory __type_to_enum() noexcept {
684  if (is_same_v<_Tp, weak_equality>)
685    return _WeakEq;
686  if (is_same_v<_Tp, strong_equality>)
687    return _StrongEq;
688  if (is_same_v<_Tp, partial_ordering>)
689    return _PartialOrd;
690  if (is_same_v<_Tp, weak_ordering>)
691    return _WeakOrd;
692  if (is_same_v<_Tp, strong_ordering>)
693    return _StrongOrd;
694  return _None;
695}
696
697template <size_t _Size>
698constexpr _ClassifyCompCategory
699__compute_comp_type(std::array<_ClassifyCompCategory, _Size> __types) {
700  std::array<int, _CCC_Size> __seen = {};
701  for (auto __type : __types)
702    ++__seen[__type];
703  if (__seen[_None])
704    return _None;
705  if (__seen[_WeakEq])
706    return _WeakEq;
707  if (__seen[_StrongEq] && (__seen[_PartialOrd] || __seen[_WeakOrd]))
708    return _WeakEq;
709  if (__seen[_StrongEq])
710    return _StrongEq;
711  if (__seen[_PartialOrd])
712    return _PartialOrd;
713  if (__seen[_WeakOrd])
714    return _WeakOrd;
715  return _StrongOrd;
716}
717
718template <class ..._Ts>
719constexpr auto __get_comp_type() {
720  using _CCC = _ClassifyCompCategory;
721  constexpr array<_CCC, sizeof...(_Ts)> __type_kinds{{__comp_detail::__type_to_enum<_Ts>()...}};
722  constexpr _CCC _Cat = sizeof...(_Ts) == 0 ? _StrongOrd
723      : __compute_comp_type(__type_kinds);
724  if constexpr (_Cat == _None)
725    return void();
726  else if constexpr (_Cat == _WeakEq)
727    return weak_equality::equivalent;
728  else if constexpr (_Cat == _StrongEq)
729    return strong_equality::equivalent;
730  else if constexpr (_Cat == _PartialOrd)
731    return partial_ordering::equivalent;
732  else if constexpr (_Cat == _WeakOrd)
733    return weak_ordering::equivalent;
734  else if constexpr (_Cat == _StrongOrd)
735    return strong_ordering::equivalent;
736  else
737    static_assert(_Cat != _Cat, "unhandled case");
738}
739} // namespace __comp_detail
740
741// [cmp.common], common comparison category type
742template<class... _Ts>
743struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
744  using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
745};
746
747template<class... _Ts>
748using common_comparison_category_t = typename common_comparison_category<_Ts...>::type;
749
750// [cmp.alg], comparison algorithms
751// TODO: unimplemented
752template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs);
753template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs);
754template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs);
755template<class _Tp> constexpr strong_equality strong_equal(const _Tp& __lhs, const _Tp& __rhs);
756template<class _Tp> constexpr weak_equality weak_equal(const _Tp& __lhs, const _Tp& __rhs);
757
758#endif // _LIBCPP_STD_VER > 17
759
760_LIBCPP_END_NAMESPACE_STD
761
762#endif // _LIBCPP_COMPARE
763