master
  1//===----------------------------------------------------------------------===//
  2//
  3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4// See https://llvm.org/LICENSE.txt for license information.
  5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6//
  7//===----------------------------------------------------------------------===//
  8
  9#ifndef _LIBCPP___COMPARE_ORDERING_H
 10#define _LIBCPP___COMPARE_ORDERING_H
 11
 12#include <__config>
 13#include <__type_traits/enable_if.h>
 14#include <__type_traits/is_same.h>
 15
 16#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 17#  pragma GCC system_header
 18#endif
 19
 20_LIBCPP_BEGIN_NAMESPACE_STD
 21
 22#if _LIBCPP_STD_VER >= 20
 23
 24// exposition only
 25enum class _OrdResult : signed char { __less = -1, __equiv = 0, __greater = 1 };
 26
 27enum class _PartialOrdResult : signed char {
 28  __less      = static_cast<signed char>(_OrdResult::__less),
 29  __equiv     = static_cast<signed char>(_OrdResult::__equiv),
 30  __greater   = static_cast<signed char>(_OrdResult::__greater),
 31  __unordered = -127,
 32};
 33
 34class partial_ordering;
 35class weak_ordering;
 36class strong_ordering;
 37
 38struct _CmpUnspecifiedParam {
 39  // If anything other than a literal 0 is provided, the behavior is undefined by the Standard.
 40  //
 41  // The alternative to the `__enable_if__` attribute would be to use the fact that a pointer
 42  // can be constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
 43  template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int> > >
 44  _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept
 45#  if __has_attribute(__enable_if__)
 46      __attribute__((__enable_if__(
 47          __zero == 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types")))
 48#  endif
 49  {
 50    (void)__zero;
 51  }
 52};
 53
 54class partial_ordering {
 55  _LIBCPP_HIDE_FROM_ABI explicit constexpr partial_ordering(_PartialOrdResult __v) noexcept : __value_(__v) {}
 56
 57public:
 58  // valid values
 59  static const partial_ordering less;
 60  static const partial_ordering equivalent;
 61  static const partial_ordering greater;
 62  static const partial_ordering unordered;
 63
 64  // comparisons
 65  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
 66
 67  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
 68    return __v.__value_ == _PartialOrdResult::__equiv;
 69  }
 70
 71  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
 72    return __v.__value_ == _PartialOrdResult::__less;
 73  }
 74
 75  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
 76    return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__less;
 77  }
 78
 79  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
 80    return __v.__value_ == _PartialOrdResult::__greater;
 81  }
 82
 83  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
 84    return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__greater;
 85  }
 86
 87  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
 88    return __v.__value_ == _PartialOrdResult::__greater;
 89  }
 90
 91  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
 92    return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__greater;
 93  }
 94
 95  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
 96    return __v.__value_ == _PartialOrdResult::__less;
 97  }
 98
 99  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
100    return __v.__value_ == _PartialOrdResult::__equiv || __v.__value_ == _PartialOrdResult::__less;
101  }
102
103  _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering
104  operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
105    return __v;
106  }
107
108  _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering
109  operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
110    return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
111  }
112
113private:
114  _PartialOrdResult __value_;
115};
116
117inline constexpr partial_ordering partial_ordering::less(_PartialOrdResult::__less);
118inline constexpr partial_ordering partial_ordering::equivalent(_PartialOrdResult::__equiv);
119inline constexpr partial_ordering partial_ordering::greater(_PartialOrdResult::__greater);
120inline constexpr partial_ordering partial_ordering::unordered(_PartialOrdResult::__unordered);
121
122class weak_ordering {
123  using _ValueT _LIBCPP_NODEBUG = signed char;
124
125  _LIBCPP_HIDE_FROM_ABI explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
126
127public:
128  static const weak_ordering less;
129  static const weak_ordering equivalent;
130  static const weak_ordering greater;
131
132  _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept {
133    return __value_ == 0 ? partial_ordering::equivalent
134                         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
135  }
136
137  // comparisons
138  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
139
140  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
141    return __v.__value_ == 0;
142  }
143
144  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
145    return __v.__value_ < 0;
146  }
147
148  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
149    return __v.__value_ <= 0;
150  }
151
152  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
153    return __v.__value_ > 0;
154  }
155
156  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
157    return __v.__value_ >= 0;
158  }
159
160  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
161    return 0 < __v.__value_;
162  }
163
164  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
165    return 0 <= __v.__value_;
166  }
167
168  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
169    return 0 > __v.__value_;
170  }
171
172  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
173    return 0 >= __v.__value_;
174  }
175
176  _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
177    return __v;
178  }
179
180  _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
181    return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
182  }
183
184private:
185  _ValueT __value_;
186};
187
188inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
189inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv);
190inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
191
192class strong_ordering {
193  using _ValueT _LIBCPP_NODEBUG = signed char;
194
195  _LIBCPP_HIDE_FROM_ABI explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
196
197public:
198  static const strong_ordering less;
199  static const strong_ordering equal;
200  static const strong_ordering equivalent;
201  static const strong_ordering greater;
202
203  // conversions
204  _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept {
205    return __value_ == 0 ? partial_ordering::equivalent
206                         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
207  }
208
209  _LIBCPP_HIDE_FROM_ABI constexpr operator weak_ordering() const noexcept {
210    return __value_ == 0 ? weak_ordering::equivalent : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
211  }
212
213  // comparisons
214  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
215
216  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
217    return __v.__value_ == 0;
218  }
219
220  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
221    return __v.__value_ < 0;
222  }
223
224  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
225    return __v.__value_ <= 0;
226  }
227
228  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
229    return __v.__value_ > 0;
230  }
231
232  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
233    return __v.__value_ >= 0;
234  }
235
236  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
237    return 0 < __v.__value_;
238  }
239
240  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
241    return 0 <= __v.__value_;
242  }
243
244  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
245    return 0 > __v.__value_;
246  }
247
248  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
249    return 0 >= __v.__value_;
250  }
251
252  _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering
253  operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
254    return __v;
255  }
256
257  _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering
258  operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
259    return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
260  }
261
262private:
263  _ValueT __value_;
264};
265
266inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
267inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv);
268inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv);
269inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
270
271/// [cmp.categories.pre]/1
272/// The types partial_ordering, weak_ordering, and strong_ordering are
273/// collectively termed the comparison category types.
274template <class _Tp>
275concept __comparison_category =
276    is_same_v<_Tp, partial_ordering> || is_same_v<_Tp, weak_ordering> || is_same_v<_Tp, strong_ordering>;
277
278#endif // _LIBCPP_STD_VER >= 20
279
280_LIBCPP_END_NAMESPACE_STD
281
282#endif // _LIBCPP___COMPARE_ORDERING_H