33 #pragma GCC system_header
35 #if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
37 #pragma GCC visibility push(default)
41 #if __cpp_lib_concepts
42 # define __cpp_lib_three_way_comparison 201711L
51 using type =
signed char;
53 enum class _Ord : type { equivalent = 0, less = -1, greater = 1 };
55 enum class _Ncmp : type { _Unordered = 2 };
59 constexpr __unspec(__unspec*) { }
63 class partial_ordering
66 __cmp_cat::type _M_value;
69 partial_ordering(__cmp_cat::_Ord __v) noexcept
70 : _M_value(__cmp_cat::type(__v))
74 partial_ordering(__cmp_cat::_Ncmp __v) noexcept
75 : _M_value(__cmp_cat::type(__v))
78 friend class weak_ordering;
79 friend class strong_ordering;
83 static const partial_ordering less;
84 static const partial_ordering equivalent;
85 static const partial_ordering greater;
86 static const partial_ordering unordered;
90 operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept
91 {
return __v._M_value == 0; }
94 operator==(partial_ordering, partial_ordering) noexcept =
default;
97 operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept
98 {
return __v._M_value == -1; }
100 friend constexpr
bool
101 operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept
102 {
return __v._M_value == 1; }
104 friend constexpr
bool
105 operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept
106 {
return __v._M_value <= 0; }
108 friend constexpr
bool
109 operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept
110 {
return __cmp_cat::type(__v._M_value & 1) == __v._M_value; }
112 friend constexpr
bool
113 operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept
114 {
return __v._M_value == 1; }
116 friend constexpr
bool
117 operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept
118 {
return __v._M_value == -1; }
120 friend constexpr
bool
121 operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept
122 {
return __cmp_cat::type(__v._M_value & 1) == __v._M_value; }
124 friend constexpr
bool
125 operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept
126 {
return 0 >= __v._M_value; }
128 friend constexpr partial_ordering
129 operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept
132 friend constexpr partial_ordering
133 operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept
135 if (__v._M_value & 1)
136 return partial_ordering(__cmp_cat::_Ord(-__v._M_value));
143 inline constexpr partial_ordering
144 partial_ordering::less(__cmp_cat::_Ord::less);
146 inline constexpr partial_ordering
147 partial_ordering::equivalent(__cmp_cat::_Ord::equivalent);
149 inline constexpr partial_ordering
150 partial_ordering::greater(__cmp_cat::_Ord::greater);
152 inline constexpr partial_ordering
153 partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered);
157 __cmp_cat::type _M_value;
160 weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v))
163 friend class strong_ordering;
167 static const weak_ordering less;
168 static const weak_ordering equivalent;
169 static const weak_ordering greater;
171 constexpr
operator partial_ordering() const noexcept
172 {
return partial_ordering(__cmp_cat::_Ord(_M_value)); }
175 friend constexpr
bool
176 operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept
177 {
return __v._M_value == 0; }
179 friend constexpr
bool
180 operator==(weak_ordering, weak_ordering) noexcept =
default;
182 friend constexpr
bool
183 operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept
184 {
return __v._M_value < 0; }
186 friend constexpr
bool
187 operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept
188 {
return __v._M_value > 0; }
190 friend constexpr
bool
191 operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept
192 {
return __v._M_value <= 0; }
194 friend constexpr
bool
195 operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept
196 {
return __v._M_value >= 0; }
198 friend constexpr
bool
199 operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept
200 {
return 0 < __v._M_value; }
202 friend constexpr
bool
203 operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept
204 {
return 0 > __v._M_value; }
206 friend constexpr
bool
207 operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept
208 {
return 0 <= __v._M_value; }
210 friend constexpr
bool
211 operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept
212 {
return 0 >= __v._M_value; }
214 friend constexpr weak_ordering
215 operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept
218 friend constexpr weak_ordering
219 operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept
220 {
return weak_ordering(__cmp_cat::_Ord(-__v._M_value)); }
224 inline constexpr weak_ordering
225 weak_ordering::less(__cmp_cat::_Ord::less);
227 inline constexpr weak_ordering
228 weak_ordering::equivalent(__cmp_cat::_Ord::equivalent);
230 inline constexpr weak_ordering
231 weak_ordering::greater(__cmp_cat::_Ord::greater);
233 class strong_ordering
235 __cmp_cat::type _M_value;
238 strong_ordering(__cmp_cat::_Ord __v) noexcept
239 : _M_value(__cmp_cat::type(__v))
244 static const strong_ordering less;
245 static const strong_ordering equal;
246 static const strong_ordering equivalent;
247 static const strong_ordering greater;
249 constexpr
operator partial_ordering() const noexcept
250 {
return partial_ordering(__cmp_cat::_Ord(_M_value)); }
252 constexpr
operator weak_ordering() const noexcept
253 {
return weak_ordering(__cmp_cat::_Ord(_M_value)); }
256 friend constexpr
bool
257 operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept
258 {
return __v._M_value == 0; }
260 friend constexpr
bool
261 operator==(strong_ordering, strong_ordering) noexcept =
default;
263 friend constexpr
bool
264 operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept
265 {
return __v._M_value < 0; }
267 friend constexpr
bool
268 operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept
269 {
return __v._M_value > 0; }
271 friend constexpr
bool
272 operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept
273 {
return __v._M_value <= 0; }
275 friend constexpr
bool
276 operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept
277 {
return __v._M_value >= 0; }
279 friend constexpr
bool
280 operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept
281 {
return 0 < __v._M_value; }
283 friend constexpr
bool
284 operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept
285 {
return 0 > __v._M_value; }
287 friend constexpr
bool
288 operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept
289 {
return 0 <= __v._M_value; }
291 friend constexpr
bool
292 operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept
293 {
return 0 >= __v._M_value; }
295 friend constexpr strong_ordering
296 operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept
299 friend constexpr strong_ordering
300 operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept
301 {
return strong_ordering(__cmp_cat::_Ord(-__v._M_value)); }
305 inline constexpr strong_ordering
306 strong_ordering::less(__cmp_cat::_Ord::less);
308 inline constexpr strong_ordering
309 strong_ordering::equal(__cmp_cat::_Ord::equivalent);
311 inline constexpr strong_ordering
312 strong_ordering::equivalent(__cmp_cat::_Ord::equivalent);
314 inline constexpr strong_ordering
315 strong_ordering::greater(__cmp_cat::_Ord::greater);
320 is_eq(partial_ordering __cmp) noexcept
321 {
return __cmp == 0; }
324 is_neq(partial_ordering __cmp) noexcept
325 {
return __cmp != 0; }
328 is_lt (partial_ordering __cmp) noexcept
329 {
return __cmp < 0; }
332 is_lteq(partial_ordering __cmp) noexcept
333 {
return __cmp <= 0; }
336 is_gt (partial_ordering __cmp) noexcept
337 {
return __cmp > 0; }
340 is_gteq(partial_ordering __cmp) noexcept
341 {
return __cmp >= 0; }
345 template<
typename _Tp>
346 inline constexpr
unsigned __cmp_cat_id = 1;
348 inline constexpr
unsigned __cmp_cat_id<partial_ordering> = 2;
350 inline constexpr
unsigned __cmp_cat_id<weak_ordering> = 4;
352 inline constexpr
unsigned __cmp_cat_id<strong_ordering> = 8;
354 template<
typename... _Ts>
355 constexpr
auto __common_cmp_cat()
357 constexpr
unsigned __cats = (__cmp_cat_id<_Ts> | ...);
359 if constexpr (__cats & 1)
363 else if constexpr (
bool(__cats & __cmp_cat_id<partial_ordering>))
364 return partial_ordering::equivalent;
367 else if constexpr (
bool(__cats & __cmp_cat_id<weak_ordering>))
368 return weak_ordering::equivalent;
371 return strong_ordering::equivalent;
376 template<
typename... _Ts>
377 struct common_comparison_category
379 using type = decltype(__detail::__common_cmp_cat<_Ts...>());
384 template<
typename _Tp>
385 struct common_comparison_category<_Tp>
386 {
using type = void; };
389 struct common_comparison_category<partial_ordering>
390 {
using type = partial_ordering; };
393 struct common_comparison_category<weak_ordering>
394 {
using type = weak_ordering; };
397 struct common_comparison_category<strong_ordering>
398 {
using type = strong_ordering; };
401 struct common_comparison_category<>
402 {
using type = strong_ordering; };
404 template<
typename... _Ts>
405 using common_comparison_category_t
406 =
typename common_comparison_category<_Ts...>::type;
408 #if __cpp_lib_concepts
411 template<
typename _Tp,
typename _Cat>
412 concept __compares_as
413 = same_as<common_comparison_category_t<_Tp, _Cat>, _Cat>;
415 template<
typename _Tp,
typename _Up>
416 concept __partially_ordered_with
417 = requires(
const remove_reference_t<_Tp>& __t,
418 const remove_reference_t<_Up>& __u) {
419 { __t < __u } -> boolean;
420 { __t > __u } -> boolean;
421 { __t <= __u } -> boolean;
422 { __t >= __u } -> boolean;
423 { __u < __t } -> boolean;
424 { __u > __t } -> boolean;
425 { __u <= __t } -> boolean;
426 { __u >= __t } -> boolean;
431 template<
typename _Tp,
typename _Cat = partial_ordering>
432 concept three_way_comparable
433 = __detail::__weakly_eq_cmp_with<_Tp, _Tp>
434 && (!convertible_to<_Cat, partial_ordering>
435 || __detail::__partially_ordered_with<_Tp, _Tp>)
436 && requires(
const remove_reference_t<_Tp>& __a,
437 const remove_reference_t<_Tp>& __b) {
438 { __a <=> __b } -> __detail::__compares_as<_Cat>;
441 template<
typename _Tp,
typename _Up,
typename _Cat = partial_ordering>
442 concept three_way_comparable_with
443 = __detail::__weakly_eq_cmp_with<_Tp, _Up>
444 && (!convertible_to<_Cat, partial_ordering>
445 || __detail::__partially_ordered_with<_Tp, _Up>)
446 && three_way_comparable<_Tp, _Cat>
447 && three_way_comparable<_Up, _Cat>
448 && common_reference_with<
const remove_reference_t<_Tp>&,
449 const remove_reference_t<_Up>&>
450 && three_way_comparable<
451 common_reference_t<
const remove_reference_t<_Tp>&,
452 const remove_reference_t<_Up>&>, _Cat>
453 && requires(
const remove_reference_t<_Tp>& __t,
454 const remove_reference_t<_Up>& __u) {
455 { __t <=> __u } -> __detail::__compares_as<_Cat>;
456 { __u <=> __t } -> __detail::__compares_as<_Cat>;
461 template<
typename _Tp,
typename _Up>
462 using __cmp3way_res_t
463 = decltype(std::declval<_Tp>() <=> std::declval<_Up>());
470 template<
typename _Tp,
typename _Up>
471 struct __cmp3way_res_impl
474 template<
typename _Tp,
typename _Up>
475 requires requires {
typename __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; }
476 struct __cmp3way_res_impl<_Tp, _Up>
478 using type = __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>;
483 template<
typename _Tp,
typename _Up = _Tp>
484 struct compare_three_way_result
485 : __detail::__cmp3way_res_impl<_Tp, _Up>
489 template<
typename _Tp,
typename _Up = _Tp>
490 using compare_three_way_result_t
491 =
typename __detail::__cmp3way_res_impl<_Tp, _Up>::type;
496 template<
typename _Tp,
typename _Up>
497 concept __3way_builtin_ptr_cmp
498 = three_way_comparable_with<_Tp, _Up>
499 && convertible_to<_Tp, const volatile void*>
500 && convertible_to<_Up, const volatile void*>
501 && ! requires(_Tp&& __t, _Up&& __u)
502 { operator<=>(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); }
503 && ! requires(_Tp&& __t, _Up&& __u)
504 { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); };
508 struct compare_three_way
510 template<
typename _Tp,
typename _Up>
511 requires three_way_comparable_with<_Tp, _Up>
513 operator()(_Tp&& __t, _Up&& __u)
const noexcept
515 if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>)
517 auto __pt = static_cast<const volatile void*>(__t);
518 auto __pu = static_cast<const volatile void*>(__u);
519 if (__builtin_is_constant_evaluated())
520 return __pt <=> __pu;
521 auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt);
522 auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu);
523 return __it <=> __iu;
526 return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u);
529 using is_transparent = void;
534 template<
floating_po
int _Tp>
535 constexpr weak_ordering
536 __fp_weak_ordering(_Tp __e, _Tp __f)
540 auto __cat = [](_Tp __fp) ->
int {
541 const int __sign = __builtin_signbit(__fp) ? -1 : 1;
542 if (__builtin_isnormal(__fp))
543 return (__fp == 0 ? 1 : 3) * __sign;
544 if (__builtin_isnan(__fp))
546 if (
int __inf = __builtin_isinf_sign(__fp))
551 auto __po = __e <=> __f;
553 return weak_ordering::less;
554 else if (is_gt(__po))
555 return weak_ordering::greater;
556 else if (__po == partial_ordering::equivalent)
557 return weak_ordering::equivalent;
561 auto __isnan_sign = [](_Tp __fp) ->
int {
562 return __builtin_isnan(__fp)
563 ? __builtin_signbit(__fp) ? -1 : 1
566 auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f);
568 return weak_ordering::equivalent;
569 else if (is_lt(__ord))
570 return weak_ordering::less;
572 return weak_ordering::greater;
576 template<
typename _Tp,
typename _Up>
577 concept __adl_strong = requires(_Tp&& __t, _Up&& __u)
579 strong_ordering(strong_order(static_cast<_Tp&&>(__t),
580 static_cast<_Up&&>(__u)));
583 template<
typename _Tp,
typename _Up>
584 concept __adl_weak = requires(_Tp&& __t, _Up&& __u)
586 weak_ordering(weak_order(static_cast<_Tp&&>(__t),
587 static_cast<_Up&&>(__u)));
590 template<
typename _Tp,
typename _Up>
591 concept __adl_partial = requires(_Tp&& __t, _Up&& __u)
593 partial_ordering(partial_order(static_cast<_Tp&&>(__t),
594 static_cast<_Up&&>(__u)));
597 template<
typename _Ord,
typename _Tp,
typename _Up>
598 concept __op_cmp = requires(_Tp&& __t, _Up&& __u)
600 _Ord(static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u));
603 template<
typename _Tp,
typename _Up>
604 concept __strongly_ordered
605 = __adl_strong<_Tp, _Up>
607 || __op_cmp<strong_ordering, _Tp, _Up>;
611 template<
typename _Tp,
typename _Up>
612 static constexpr
bool
615 if constexpr (floating_point<decay_t<_Tp>>)
617 else if constexpr (__adl_strong<_Tp, _Up>)
618 return noexcept(strong_ordering(strong_order(
std::declval<_Tp>(),
619 std::declval<_Up>())));
620 else if constexpr (__op_cmp<strong_ordering, _Tp, _Up>)
621 return noexcept(
std::declval<_Tp>() <=>
std::declval<_Up>());
624 friend class _Weak_order;
625 friend class _Strong_fallback;
628 template<typename _Tp, typename _Up>
629 requires __strongly_ordered<_Tp, _Up>
630 constexpr strong_ordering
631 operator()(_Tp&& __e, _Up&& __f) const
632 noexcept(_S_noexcept<_Tp, _Up>())
634 static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
639 if constexpr (__adl_strong<_Tp, _Up>)
640 return strong_ordering(strong_order(static_cast<_Tp&&>(__e),
641 static_cast<_Up&&>(__f)));
642 else if constexpr (__op_cmp<strong_ordering, _Tp, _Up>)
643 return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f);
647 template<
typename _Tp,
typename _Up>
648 concept __weakly_ordered
649 = floating_point<remove_reference_t<_Tp>>
650 || __adl_weak<_Tp, _Up>
651 || __op_cmp<weak_ordering, _Tp, _Up>
652 || __strongly_ordered<_Tp, _Up>;
656 template<
typename _Tp,
typename _Up>
657 static constexpr
bool
660 if constexpr (floating_point<decay_t<_Tp>>)
662 else if constexpr (__adl_weak<_Tp, _Up>)
663 return noexcept(weak_ordering(weak_order(
std::declval<_Tp>(),
664 std::declval<_Up>())));
665 else if constexpr (__op_cmp<weak_ordering, _Tp, _Up>)
666 return noexcept(
std::declval<_Tp>() <=>
std::declval<_Up>());
667 else if constexpr (__strongly_ordered<_Tp, _Up>)
668 return _Strong_order::_S_noexcept<_Tp, _Up>();
671 friend class _Partial_order;
672 friend class _Weak_fallback;
675 template<typename _Tp, typename _Up>
676 requires __weakly_ordered<_Tp, _Up>
677 constexpr weak_ordering
678 operator()(_Tp&& __e, _Up&& __f) const
679 noexcept(_S_noexcept<_Tp, _Up>())
681 static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
683 if constexpr (floating_point<decay_t<_Tp>>)
684 return __cmp_cust::__fp_weak_ordering(__e, __f);
685 else if constexpr (__adl_weak<_Tp, _Up>)
686 return weak_ordering(weak_order(static_cast<_Tp&&>(__e),
687 static_cast<_Up&&>(__f)));
688 else if constexpr (__op_cmp<weak_ordering, _Tp, _Up>)
689 return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f);
690 else if constexpr (__strongly_ordered<_Tp, _Up>)
691 return _Strong_order{}(static_cast<_Tp&&>(__e),
692 static_cast<_Up&&>(__f));
696 template<
typename _Tp,
typename _Up>
697 concept __partially_ordered
698 = __adl_partial<_Tp, _Up>
699 || __op_cmp<partial_ordering, _Tp, _Up>
700 || __weakly_ordered<_Tp, _Up>;
704 template<
typename _Tp,
typename _Up>
705 static constexpr
bool
708 if constexpr (__adl_partial<_Tp, _Up>)
709 return noexcept(partial_ordering(partial_order(std::declval<_Tp>(),
710 std::declval<_Up>())));
711 else if constexpr (__op_cmp<partial_ordering, _Tp, _Up>)
712 return noexcept(std::declval<_Tp>() <=> std::declval<_Up>());
713 else if constexpr (__weakly_ordered<_Tp, _Up>)
714 return _Weak_order::_S_noexcept<_Tp, _Up>();
717 friend class _Partial_fallback;
720 template<
typename _Tp,
typename _Up>
721 requires __partially_ordered<_Tp, _Up>
722 constexpr partial_ordering
723 operator()(_Tp&& __e, _Up&& __f)
const
724 noexcept(_S_noexcept<_Tp, _Up>())
726 static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
728 if constexpr (__adl_partial<_Tp, _Up>)
729 return partial_ordering(partial_order(static_cast<_Tp&&>(__e),
730 static_cast<_Up&&>(__f)));
731 else if constexpr (__op_cmp<partial_ordering, _Tp, _Up>)
732 return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f);
733 else if constexpr (__weakly_ordered<_Tp, _Up>)
734 return _Weak_order{}(static_cast<_Tp&&>(__e),
735 static_cast<_Up&&>(__f));
739 template<
typename _Tp,
typename _Up>
740 concept __op_eq_lt = requires(_Tp&& __t, _Up&& __u)
742 { static_cast<_Tp&&>(__t) == static_cast<_Up&&>(__u) }
743 -> convertible_to<bool>;
744 { static_cast<_Tp&&>(__t) < static_cast<_Up&&>(__u) }
745 -> convertible_to<bool>;
748 class _Strong_fallback
750 template<
typename _Tp,
typename _Up>
751 static constexpr
bool
754 if constexpr (__strongly_ordered<_Tp, _Up>)
755 return _Strong_order::_S_noexcept<_Tp, _Up>();
757 return noexcept(
bool(std::declval<_Tp>() == std::declval<_Up>()))
758 && noexcept(
bool(std::declval<_Tp>() < std::declval<_Up>()));
762 template<
typename _Tp,
typename _Up>
763 requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up>
764 constexpr decltype(
auto)
765 operator()(_Tp&& __e, _Up&& __f) const
766 noexcept(_S_noexcept<_Tp, _Up>())
768 static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
770 if constexpr (__strongly_ordered<_Tp, _Up>)
771 return _Strong_order{}(static_cast<_Tp&&>(__e),
772 static_cast<_Up&&>(__f));
773 else if constexpr (__op_eq_lt<_Tp, _Up>)
774 return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f)
775 ? strong_ordering::equal
776 : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f)
777 ? strong_ordering::less
778 : strong_ordering::greater;
784 template<
typename _Tp,
typename _Up>
785 static constexpr
bool
788 if constexpr (__weakly_ordered<_Tp, _Up>)
789 return _Weak_order::_S_noexcept<_Tp, _Up>();
791 return noexcept(
bool(std::declval<_Tp>() == std::declval<_Up>()))
792 && noexcept(
bool(std::declval<_Tp>() < std::declval<_Up>()));
796 template<
typename _Tp,
typename _Up>
797 requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up>
798 constexpr decltype(
auto)
799 operator()(_Tp&& __e, _Up&& __f) const
800 noexcept(_S_noexcept<_Tp, _Up>())
802 static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
804 if constexpr (__weakly_ordered<_Tp, _Up>)
805 return _Weak_order{}(static_cast<_Tp&&>(__e),
806 static_cast<_Up&&>(__f));
807 else if constexpr (__op_eq_lt<_Tp, _Up>)
808 return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f)
809 ? weak_ordering::equivalent
810 : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f)
811 ? weak_ordering::less
812 : weak_ordering::greater;
816 class _Partial_fallback
818 template<
typename _Tp,
typename _Up>
819 static constexpr
bool
822 if constexpr (__partially_ordered<_Tp, _Up>)
823 return _Partial_order::_S_noexcept<_Tp, _Up>();
825 return noexcept(
bool(std::declval<_Tp>() == std::declval<_Up>()))
826 && noexcept(
bool(std::declval<_Tp>() < std::declval<_Up>()));
830 template<
typename _Tp,
typename _Up>
831 requires __partially_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up>
832 constexpr decltype(
auto)
833 operator()(_Tp&& __e, _Up&& __f) const
834 noexcept(_S_noexcept<_Tp, _Up>())
836 static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
838 if constexpr (__partially_ordered<_Tp, _Up>)
839 return _Partial_order{}(static_cast<_Tp&&>(__e),
840 static_cast<_Up&&>(__f));
841 else if constexpr (__op_eq_lt<_Tp, _Up>)
842 return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f)
843 ? partial_ordering::equivalent
844 : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f)
845 ? partial_ordering::less
846 : static_cast<_Up&&>(__f) < static_cast<_Tp&&>(__e)
847 ? partial_ordering::greater
848 : partial_ordering::unordered;
854 inline namespace __cmp_alg
856 inline constexpr __cmp_cust::_Strong_order strong_order{};
858 inline constexpr __cmp_cust::_Weak_order weak_order{};
860 inline constexpr __cmp_cust::_Partial_order partial_order{};
862 inline constexpr __cmp_cust::_Strong_fallback
863 compare_strong_order_fallback{};
865 inline constexpr __cmp_cust::_Weak_fallback
866 compare_weak_order_fallback{};
868 inline constexpr __cmp_cust::_Partial_fallback
869 compare_partial_order_fallback{};
875 inline constexpr
struct _Synth3way
877 template<
typename _Tp,
typename _Up>
879 operator()(
const _Tp& __t,
const _Up& __u)
const
882 { __t < __u } -> convertible_to<bool>;
883 { __u < __t } -> convertible_to<bool>;
886 if constexpr (three_way_comparable_with<_Tp, _Up>)
891 return weak_ordering::less;
893 return weak_ordering::greater;
895 return weak_ordering::equivalent;
900 template<
typename _Tp,
typename _Up = _Tp>
902 = decltype(__detail::__synth3way(std::declval<_Tp&>(),
903 std::declval<_Up&>()));
908 #pragma GCC visibility pop