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