1 #ifndef STD_COMPARE_H
2 #define STD_COMPARE_H
3 
4 namespace std {
5 inline namespace __1 {
6 
7 // exposition only
8 enum class _EqResult : unsigned char {
9   __zero = 0,
10   __equal = __zero,
11   __equiv = __equal,
12   __nonequal = 1,
13   __nonequiv = __nonequal
14 };
15 
16 enum class _OrdResult : signed char {
17   __less = -1,
18   __greater = 1
19 };
20 
21 enum class _NCmpResult : signed char {
22   __unordered = -127
23 };
24 
25 struct _CmpUnspecifiedType;
26 using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
27 
28 class weak_equality {
29   constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
30 
31 public:
32   static const weak_equality equivalent;
33   static const weak_equality nonequivalent;
34 
35   friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
36   friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
37   friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
38   friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
39   friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
40   friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
41 
42   // test helper
43   constexpr bool test_eq(weak_equality const &other) const noexcept {
44     return __value_ == other.__value_;
45   }
46 
47 private:
48   _EqResult __value_;
49 };
50 
51 inline constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
52 inline constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
53 inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
54   return __v.__value_ == _EqResult::__zero;
55 }
56 inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
57   return __v.__value_ == _EqResult::__zero;
58 }
59 inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
60   return __v.__value_ != _EqResult::__zero;
61 }
62 inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
63   return __v.__value_ != _EqResult::__zero;
64 }
65 
66 inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
67   return __v;
68 }
69 inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
70   return __v;
71 }
72 
73 class strong_equality {
74   explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
75 
76 public:
77   static const strong_equality equal;
78   static const strong_equality nonequal;
79   static const strong_equality equivalent;
80   static const strong_equality nonequivalent;
81 
82   // conversion
83   constexpr operator weak_equality() const noexcept {
84     return __value_ == _EqResult::__zero ? weak_equality::equivalent
85                                          : weak_equality::nonequivalent;
86   }
87 
88   // comparisons
89   friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
90   friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
91   friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
92   friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
93 
94   friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
95   friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
96 
97   // test helper
98   constexpr bool test_eq(strong_equality const &other) const noexcept {
99     return __value_ == other.__value_;
100   }
101 
102 private:
103   _EqResult __value_;
104 };
105 
106 inline constexpr strong_equality strong_equality::equal(_EqResult::__equal);
107 inline constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
108 inline constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
109 inline constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
110 constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
111   return __v.__value_ == _EqResult::__zero;
112 }
113 constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
114   return __v.__value_ == _EqResult::__zero;
115 }
116 constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
117   return __v.__value_ != _EqResult::__zero;
118 }
119 constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
120   return __v.__value_ != _EqResult::__zero;
121 }
122 
123 constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
124   return __v;
125 }
126 constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
127   return __v;
128 }
129 
130 class partial_ordering {
131   using _ValueT = signed char;
132   explicit constexpr partial_ordering(_EqResult __v) noexcept
133       : __value_(_ValueT(__v)) {}
134   explicit constexpr partial_ordering(_OrdResult __v) noexcept
135       : __value_(_ValueT(__v)) {}
136   explicit constexpr partial_ordering(_NCmpResult __v) noexcept
137       : __value_(_ValueT(__v)) {}
138 
139   constexpr bool __is_ordered() const noexcept {
140     return __value_ != _ValueT(_NCmpResult::__unordered);
141   }
142 
143 public:
144   // valid values
145   static const partial_ordering less;
146   static const partial_ordering equivalent;
147   static const partial_ordering greater;
148   static const partial_ordering unordered;
149 
150   // conversion
151   constexpr operator weak_equality() const noexcept {
152     return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
153   }
154 
155   // comparisons
156   friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
157   friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
158   friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
159   friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
160   friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
161   friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
162   friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
163   friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
164   friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
165   friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
166   friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
167   friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
168 
169   friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
170   friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
171 
172   // test helper
173   constexpr bool test_eq(partial_ordering const &other) const noexcept {
174     return __value_ == other.__value_;
175   }
176 
177 private:
178   _ValueT __value_;
179 };
180 
181 inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
182 inline constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
183 inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
184 inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
185 constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
186   return __v.__is_ordered() && __v.__value_ == 0;
187 }
188 constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
189   return __v.__is_ordered() && __v.__value_ < 0;
190 }
191 constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
192   return __v.__is_ordered() && __v.__value_ <= 0;
193 }
194 constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
195   return __v.__is_ordered() && __v.__value_ > 0;
196 }
197 constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
198   return __v.__is_ordered() && __v.__value_ >= 0;
199 }
200 constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
201   return __v.__is_ordered() && 0 == __v.__value_;
202 }
203 constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
204   return __v.__is_ordered() && 0 < __v.__value_;
205 }
206 constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
207   return __v.__is_ordered() && 0 <= __v.__value_;
208 }
209 constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
210   return __v.__is_ordered() && 0 > __v.__value_;
211 }
212 constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
213   return __v.__is_ordered() && 0 >= __v.__value_;
214 }
215 constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
216   return !__v.__is_ordered() || __v.__value_ != 0;
217 }
218 constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
219   return !__v.__is_ordered() || __v.__value_ != 0;
220 }
221 
222 constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
223   return __v;
224 }
225 constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
226   return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
227 }
228 
229 class weak_ordering {
230   using _ValueT = signed char;
231   explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
232   explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
233 
234 public:
235   static const weak_ordering less;
236   static const weak_ordering equivalent;
237   static const weak_ordering greater;
238 
239   // conversions
240   constexpr operator weak_equality() const noexcept {
241     return __value_ == 0 ? weak_equality::equivalent
242                          : weak_equality::nonequivalent;
243   }
244   constexpr operator partial_ordering() const noexcept {
245     return __value_ == 0 ? partial_ordering::equivalent
246                          : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
247   }
248 
249   // comparisons
250   friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
251   friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
252   friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
253   friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
254   friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
255   friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
256   friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
257   friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
258   friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
259   friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
260   friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
261   friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
262 
263   friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
264   friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
265 
266   // test helper
267   constexpr bool test_eq(weak_ordering const &other) const noexcept {
268     return __value_ == other.__value_;
269   }
270 
271 private:
272   _ValueT __value_;
273 };
274 
275 inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
276 inline constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
277 inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
278 constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
279   return __v.__value_ == 0;
280 }
281 constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
282   return __v.__value_ != 0;
283 }
284 constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
285   return __v.__value_ < 0;
286 }
287 constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
288   return __v.__value_ <= 0;
289 }
290 constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
291   return __v.__value_ > 0;
292 }
293 constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
294   return __v.__value_ >= 0;
295 }
296 constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
297   return 0 == __v.__value_;
298 }
299 constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
300   return 0 != __v.__value_;
301 }
302 constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
303   return 0 < __v.__value_;
304 }
305 constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
306   return 0 <= __v.__value_;
307 }
308 constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
309   return 0 > __v.__value_;
310 }
311 constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
312   return 0 >= __v.__value_;
313 }
314 
315 constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
316   return __v;
317 }
318 constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
319   return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
320 }
321 
322 class strong_ordering {
323   using _ValueT = signed char;
324   explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
325   explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(static_cast<signed char>(__v)) {}
326 
327 public:
328   static const strong_ordering less;
329   static const strong_ordering equal;
330   static const strong_ordering equivalent;
331   static const strong_ordering greater;
332 
333   // conversions
334   constexpr operator weak_equality() const noexcept {
335     return __value_ == 0 ? weak_equality::equivalent
336                          : weak_equality::nonequivalent;
337   }
338   constexpr operator strong_equality() const noexcept {
339     return __value_ == 0 ? strong_equality::equal
340                          : strong_equality::nonequal;
341   }
342   constexpr operator partial_ordering() const noexcept {
343     return __value_ == 0 ? partial_ordering::equivalent
344                          : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
345   }
346   constexpr operator weak_ordering() const noexcept {
347     return __value_ == 0 ? weak_ordering::equivalent
348                          : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
349   }
350 
351   // comparisons
352   friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
353   friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
354   friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
355   friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
356   friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
357   friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
358   friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
359   friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
360   friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
361   friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
362   friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
363   friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
364 
365   friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
366   friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
367 
368   // test helper
369   constexpr bool test_eq(strong_ordering const &other) const noexcept {
370     return __value_ == other.__value_;
371   }
372 
373 private:
374   _ValueT __value_;
375 };
376 
377 inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
378 inline constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
379 inline constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
380 inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
381 
382 constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
383   return __v.__value_ == 0;
384 }
385 constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
386   return __v.__value_ != 0;
387 }
388 constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
389   return __v.__value_ < 0;
390 }
391 constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
392   return __v.__value_ <= 0;
393 }
394 constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
395   return __v.__value_ > 0;
396 }
397 constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
398   return __v.__value_ >= 0;
399 }
400 constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
401   return 0 == __v.__value_;
402 }
403 constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
404   return 0 != __v.__value_;
405 }
406 constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
407   return 0 < __v.__value_;
408 }
409 constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
410   return 0 <= __v.__value_;
411 }
412 constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
413   return 0 > __v.__value_;
414 }
415 constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
416   return 0 >= __v.__value_;
417 }
418 
419 constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
420   return __v;
421 }
422 constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
423   return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
424 }
425 
426 // named comparison functions
427 constexpr bool is_eq(weak_equality __cmp) noexcept { return __cmp == 0; }
428 constexpr bool is_neq(weak_equality __cmp) noexcept { return __cmp != 0; }
429 constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
430 constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
431 constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
432 constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
433 
434 } // namespace __1
435 } // end namespace std
436 
437 #endif // STD_COMPARE_H
438