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 > 17
23 
24 // exposition only
25 enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {
26   __less = -1,
27   __equiv = 0,
28   __greater = 1
29 };
30 
31 enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
32   __unordered = -127
33 };
34 
35 class partial_ordering;
36 class weak_ordering;
37 class strong_ordering;
38 
39 template<class _Tp, class... _Args>
40 inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...);
41 
42 struct _CmpUnspecifiedParam {
43   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL
44   _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
45 
46   template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>>
47   _CmpUnspecifiedParam(_Tp) = delete;
48 };
49 
50 class partial_ordering {
51   using _ValueT = signed char;
52 
53   _LIBCPP_HIDE_FROM_ABI
54   explicit constexpr partial_ordering(_OrdResult __v) noexcept
55       : __value_(_ValueT(__v)) {}
56 
57   _LIBCPP_HIDE_FROM_ABI
58   explicit constexpr partial_ordering(_NCmpResult __v) noexcept
59       : __value_(_ValueT(__v)) {}
60 
61   _LIBCPP_HIDE_FROM_ABI
62   constexpr bool __is_ordered() const noexcept {
63     return __value_ != _ValueT(_NCmpResult::__unordered);
64   }
65 public:
66   // valid values
67   static const partial_ordering less;
68   static const partial_ordering equivalent;
69   static const partial_ordering greater;
70   static const partial_ordering unordered;
71 
72   // comparisons
73   _LIBCPP_HIDE_FROM_ABI
74   friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
75 
76   _LIBCPP_HIDE_FROM_ABI
77   friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
78     return __v.__is_ordered() && __v.__value_ == 0;
79   }
80 
81   _LIBCPP_HIDE_FROM_ABI
82   friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
83     return __v.__is_ordered() && __v.__value_ < 0;
84   }
85 
86   _LIBCPP_HIDE_FROM_ABI
87   friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
88     return __v.__is_ordered() && __v.__value_ <= 0;
89   }
90 
91   _LIBCPP_HIDE_FROM_ABI
92   friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
93     return __v.__is_ordered() && __v.__value_ > 0;
94   }
95 
96   _LIBCPP_HIDE_FROM_ABI
97   friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
98     return __v.__is_ordered() && __v.__value_ >= 0;
99   }
100 
101   _LIBCPP_HIDE_FROM_ABI
102   friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
103     return __v.__is_ordered() && 0 < __v.__value_;
104   }
105 
106   _LIBCPP_HIDE_FROM_ABI
107   friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
108     return __v.__is_ordered() && 0 <= __v.__value_;
109   }
110 
111   _LIBCPP_HIDE_FROM_ABI
112   friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
113     return __v.__is_ordered() && 0 > __v.__value_;
114   }
115 
116   _LIBCPP_HIDE_FROM_ABI
117   friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
118     return __v.__is_ordered() && 0 >= __v.__value_;
119   }
120 
121   _LIBCPP_HIDE_FROM_ABI
122   friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
123     return __v;
124   }
125 
126   _LIBCPP_HIDE_FROM_ABI
127   friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
128     return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
129   }
130 private:
131   _ValueT __value_;
132 };
133 
134 inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
135 inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv);
136 inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
137 inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
138 
139 class weak_ordering {
140   using _ValueT = signed char;
141 
142   _LIBCPP_HIDE_FROM_ABI
143   explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
144 
145 public:
146   static const weak_ordering less;
147   static const weak_ordering equivalent;
148   static const weak_ordering greater;
149 
150   _LIBCPP_HIDE_FROM_ABI
151   constexpr operator partial_ordering() const noexcept {
152     return __value_ == 0 ? partial_ordering::equivalent
153         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
154   }
155 
156   // comparisons
157   _LIBCPP_HIDE_FROM_ABI
158   friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
159 
160   _LIBCPP_HIDE_FROM_ABI
161   friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
162     return __v.__value_ == 0;
163   }
164 
165   _LIBCPP_HIDE_FROM_ABI
166   friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
167     return __v.__value_ < 0;
168   }
169 
170   _LIBCPP_HIDE_FROM_ABI
171   friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
172     return __v.__value_ <= 0;
173   }
174 
175   _LIBCPP_HIDE_FROM_ABI
176   friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
177     return __v.__value_ > 0;
178   }
179 
180   _LIBCPP_HIDE_FROM_ABI
181   friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
182     return __v.__value_ >= 0;
183   }
184 
185   _LIBCPP_HIDE_FROM_ABI
186   friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
187     return 0 < __v.__value_;
188   }
189 
190   _LIBCPP_HIDE_FROM_ABI
191   friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
192     return 0 <= __v.__value_;
193   }
194 
195   _LIBCPP_HIDE_FROM_ABI
196   friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
197     return 0 > __v.__value_;
198   }
199 
200   _LIBCPP_HIDE_FROM_ABI
201   friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
202     return 0 >= __v.__value_;
203   }
204 
205   _LIBCPP_HIDE_FROM_ABI
206   friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
207     return __v;
208   }
209 
210   _LIBCPP_HIDE_FROM_ABI
211   friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
212     return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
213   }
214 
215 private:
216   _ValueT __value_;
217 };
218 
219 inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
220 inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv);
221 inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
222 
223 class strong_ordering {
224   using _ValueT = signed char;
225 
226   _LIBCPP_HIDE_FROM_ABI
227   explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
228 
229 public:
230   static const strong_ordering less;
231   static const strong_ordering equal;
232   static const strong_ordering equivalent;
233   static const strong_ordering greater;
234 
235   // conversions
236   _LIBCPP_HIDE_FROM_ABI
237   constexpr operator partial_ordering() const noexcept {
238     return __value_ == 0 ? partial_ordering::equivalent
239         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
240   }
241 
242   _LIBCPP_HIDE_FROM_ABI
243   constexpr operator weak_ordering() const noexcept {
244     return __value_ == 0 ? weak_ordering::equivalent
245         : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
246   }
247 
248   // comparisons
249   _LIBCPP_HIDE_FROM_ABI
250   friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
251 
252   _LIBCPP_HIDE_FROM_ABI
253   friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
254     return __v.__value_ == 0;
255   }
256 
257   _LIBCPP_HIDE_FROM_ABI
258   friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
259     return __v.__value_ < 0;
260   }
261 
262   _LIBCPP_HIDE_FROM_ABI
263   friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
264     return __v.__value_ <= 0;
265   }
266 
267   _LIBCPP_HIDE_FROM_ABI
268   friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
269     return __v.__value_ > 0;
270   }
271 
272   _LIBCPP_HIDE_FROM_ABI
273   friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
274     return __v.__value_ >= 0;
275   }
276 
277   _LIBCPP_HIDE_FROM_ABI
278   friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
279     return 0 < __v.__value_;
280   }
281 
282   _LIBCPP_HIDE_FROM_ABI
283   friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
284     return 0 <= __v.__value_;
285   }
286 
287   _LIBCPP_HIDE_FROM_ABI
288   friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
289     return 0 > __v.__value_;
290   }
291 
292   _LIBCPP_HIDE_FROM_ABI
293   friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
294     return 0 >= __v.__value_;
295   }
296 
297   _LIBCPP_HIDE_FROM_ABI
298   friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
299     return __v;
300   }
301 
302   _LIBCPP_HIDE_FROM_ABI
303   friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
304     return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
305   }
306 
307 private:
308   _ValueT __value_;
309 };
310 
311 inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
312 inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv);
313 inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv);
314 inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
315 
316 /// [cmp.categories.pre]/1
317 /// The types partial_ordering, weak_ordering, and strong_ordering are
318 /// collectively termed the comparison category types.
319 template <class _Tp>
320 concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>;
321 
322 #endif // _LIBCPP_STD_VER > 17
323 
324 _LIBCPP_END_NAMESPACE_STD
325 
326 #endif // _LIBCPP___COMPARE_ORDERING_H
327