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