compare 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. // -*- C++ -*- operator<=> three-way comparison support.
  2. // Copyright (C) 2019-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of GCC.
  5. //
  6. // GCC is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10. //
  11. // GCC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19. // You should have received a copy of the GNU General Public License and
  20. // a copy of the GCC Runtime Library Exception along with this program;
  21. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  22. // <http://www.gnu.org/licenses/>.
  23. /** @file compare
  24. * This is a Standard C++ Library header.
  25. */
  26. #ifndef _COMPARE
  27. #define _COMPARE
  28. #pragma GCC system_header
  29. #if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
  30. #pragma GCC visibility push(default)
  31. #include <concepts>
  32. #if __cpp_lib_concepts
  33. # define __cpp_lib_three_way_comparison 201907L
  34. #endif
  35. namespace std
  36. {
  37. // [cmp.categories], comparison category types
  38. namespace __cmp_cat
  39. {
  40. using type = signed char;
  41. enum class _Ord : type { equivalent = 0, less = -1, greater = 1 };
  42. enum class _Ncmp : type { _Unordered = 2 };
  43. struct __unspec
  44. {
  45. constexpr __unspec(__unspec*) noexcept { }
  46. };
  47. }
  48. class partial_ordering
  49. {
  50. // less=0xff, equiv=0x00, greater=0x01, unordered=0x02
  51. __cmp_cat::type _M_value;
  52. constexpr explicit
  53. partial_ordering(__cmp_cat::_Ord __v) noexcept
  54. : _M_value(__cmp_cat::type(__v))
  55. { }
  56. constexpr explicit
  57. partial_ordering(__cmp_cat::_Ncmp __v) noexcept
  58. : _M_value(__cmp_cat::type(__v))
  59. { }
  60. friend class weak_ordering;
  61. friend class strong_ordering;
  62. public:
  63. // valid values
  64. static const partial_ordering less;
  65. static const partial_ordering equivalent;
  66. static const partial_ordering greater;
  67. static const partial_ordering unordered;
  68. // comparisons
  69. friend constexpr bool
  70. operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept
  71. { return __v._M_value == 0; }
  72. friend constexpr bool
  73. operator==(partial_ordering, partial_ordering) noexcept = default;
  74. friend constexpr bool
  75. operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept
  76. { return __v._M_value == -1; }
  77. friend constexpr bool
  78. operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept
  79. { return __v._M_value == 1; }
  80. friend constexpr bool
  81. operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept
  82. { return __v._M_value <= 0; }
  83. friend constexpr bool
  84. operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept
  85. { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; }
  86. friend constexpr bool
  87. operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept
  88. { return __v._M_value == 1; }
  89. friend constexpr bool
  90. operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept
  91. { return __v._M_value == -1; }
  92. friend constexpr bool
  93. operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept
  94. { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; }
  95. friend constexpr bool
  96. operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept
  97. { return 0 >= __v._M_value; }
  98. friend constexpr partial_ordering
  99. operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept
  100. { return __v; }
  101. friend constexpr partial_ordering
  102. operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept
  103. {
  104. if (__v._M_value & 1)
  105. return partial_ordering(__cmp_cat::_Ord(-__v._M_value));
  106. else
  107. return __v;
  108. }
  109. };
  110. // valid values' definitions
  111. inline constexpr partial_ordering
  112. partial_ordering::less(__cmp_cat::_Ord::less);
  113. inline constexpr partial_ordering
  114. partial_ordering::equivalent(__cmp_cat::_Ord::equivalent);
  115. inline constexpr partial_ordering
  116. partial_ordering::greater(__cmp_cat::_Ord::greater);
  117. inline constexpr partial_ordering
  118. partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered);
  119. class weak_ordering
  120. {
  121. __cmp_cat::type _M_value;
  122. constexpr explicit
  123. weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v))
  124. { }
  125. friend class strong_ordering;
  126. public:
  127. // valid values
  128. static const weak_ordering less;
  129. static const weak_ordering equivalent;
  130. static const weak_ordering greater;
  131. constexpr operator partial_ordering() const noexcept
  132. { return partial_ordering(__cmp_cat::_Ord(_M_value)); }
  133. // comparisons
  134. friend constexpr bool
  135. operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept
  136. { return __v._M_value == 0; }
  137. friend constexpr bool
  138. operator==(weak_ordering, weak_ordering) noexcept = default;
  139. friend constexpr bool
  140. operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept
  141. { return __v._M_value < 0; }
  142. friend constexpr bool
  143. operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept
  144. { return __v._M_value > 0; }
  145. friend constexpr bool
  146. operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept
  147. { return __v._M_value <= 0; }
  148. friend constexpr bool
  149. operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept
  150. { return __v._M_value >= 0; }
  151. friend constexpr bool
  152. operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept
  153. { return 0 < __v._M_value; }
  154. friend constexpr bool
  155. operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept
  156. { return 0 > __v._M_value; }
  157. friend constexpr bool
  158. operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept
  159. { return 0 <= __v._M_value; }
  160. friend constexpr bool
  161. operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept
  162. { return 0 >= __v._M_value; }
  163. friend constexpr weak_ordering
  164. operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept
  165. { return __v; }
  166. friend constexpr weak_ordering
  167. operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept
  168. { return weak_ordering(__cmp_cat::_Ord(-__v._M_value)); }
  169. };
  170. // valid values' definitions
  171. inline constexpr weak_ordering
  172. weak_ordering::less(__cmp_cat::_Ord::less);
  173. inline constexpr weak_ordering
  174. weak_ordering::equivalent(__cmp_cat::_Ord::equivalent);
  175. inline constexpr weak_ordering
  176. weak_ordering::greater(__cmp_cat::_Ord::greater);
  177. class strong_ordering
  178. {
  179. __cmp_cat::type _M_value;
  180. constexpr explicit
  181. strong_ordering(__cmp_cat::_Ord __v) noexcept
  182. : _M_value(__cmp_cat::type(__v))
  183. { }
  184. public:
  185. // valid values
  186. static const strong_ordering less;
  187. static const strong_ordering equal;
  188. static const strong_ordering equivalent;
  189. static const strong_ordering greater;
  190. constexpr operator partial_ordering() const noexcept
  191. { return partial_ordering(__cmp_cat::_Ord(_M_value)); }
  192. constexpr operator weak_ordering() const noexcept
  193. { return weak_ordering(__cmp_cat::_Ord(_M_value)); }
  194. // comparisons
  195. friend constexpr bool
  196. operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept
  197. { return __v._M_value == 0; }
  198. friend constexpr bool
  199. operator==(strong_ordering, strong_ordering) noexcept = default;
  200. friend constexpr bool
  201. operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept
  202. { return __v._M_value < 0; }
  203. friend constexpr bool
  204. operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept
  205. { return __v._M_value > 0; }
  206. friend constexpr bool
  207. operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept
  208. { return __v._M_value <= 0; }
  209. friend constexpr bool
  210. operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept
  211. { return __v._M_value >= 0; }
  212. friend constexpr bool
  213. operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept
  214. { return 0 < __v._M_value; }
  215. friend constexpr bool
  216. operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept
  217. { return 0 > __v._M_value; }
  218. friend constexpr bool
  219. operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept
  220. { return 0 <= __v._M_value; }
  221. friend constexpr bool
  222. operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept
  223. { return 0 >= __v._M_value; }
  224. friend constexpr strong_ordering
  225. operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept
  226. { return __v; }
  227. friend constexpr strong_ordering
  228. operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept
  229. { return strong_ordering(__cmp_cat::_Ord(-__v._M_value)); }
  230. };
  231. // valid values' definitions
  232. inline constexpr strong_ordering
  233. strong_ordering::less(__cmp_cat::_Ord::less);
  234. inline constexpr strong_ordering
  235. strong_ordering::equal(__cmp_cat::_Ord::equivalent);
  236. inline constexpr strong_ordering
  237. strong_ordering::equivalent(__cmp_cat::_Ord::equivalent);
  238. inline constexpr strong_ordering
  239. strong_ordering::greater(__cmp_cat::_Ord::greater);
  240. // named comparison functions
  241. constexpr bool
  242. is_eq(partial_ordering __cmp) noexcept
  243. { return __cmp == 0; }
  244. constexpr bool
  245. is_neq(partial_ordering __cmp) noexcept
  246. { return __cmp != 0; }
  247. constexpr bool
  248. is_lt (partial_ordering __cmp) noexcept
  249. { return __cmp < 0; }
  250. constexpr bool
  251. is_lteq(partial_ordering __cmp) noexcept
  252. { return __cmp <= 0; }
  253. constexpr bool
  254. is_gt (partial_ordering __cmp) noexcept
  255. { return __cmp > 0; }
  256. constexpr bool
  257. is_gteq(partial_ordering __cmp) noexcept
  258. { return __cmp >= 0; }
  259. namespace __detail
  260. {
  261. template<typename _Tp>
  262. inline constexpr unsigned __cmp_cat_id = 1;
  263. template<>
  264. inline constexpr unsigned __cmp_cat_id<partial_ordering> = 2;
  265. template<>
  266. inline constexpr unsigned __cmp_cat_id<weak_ordering> = 4;
  267. template<>
  268. inline constexpr unsigned __cmp_cat_id<strong_ordering> = 8;
  269. template<typename... _Ts>
  270. constexpr auto __common_cmp_cat()
  271. {
  272. constexpr unsigned __cats = (__cmp_cat_id<_Ts> | ...);
  273. // If any Ti is not a comparison category type, U is void.
  274. if constexpr (__cats & 1)
  275. return;
  276. // Otherwise, if at least one Ti is std::partial_ordering,
  277. // U is std::partial_ordering.
  278. else if constexpr (bool(__cats & __cmp_cat_id<partial_ordering>))
  279. return partial_ordering::equivalent;
  280. // Otherwise, if at least one Ti is std::weak_ordering,
  281. // U is std::weak_ordering.
  282. else if constexpr (bool(__cats & __cmp_cat_id<weak_ordering>))
  283. return weak_ordering::equivalent;
  284. // Otherwise, U is std::strong_ordering.
  285. else
  286. return strong_ordering::equivalent;
  287. }
  288. } // namespace __detail
  289. // [cmp.common], common comparison category type
  290. template<typename... _Ts>
  291. struct common_comparison_category
  292. {
  293. using type = decltype(__detail::__common_cmp_cat<_Ts...>());
  294. };
  295. // Partial specializations for one and zero argument cases.
  296. template<typename _Tp>
  297. struct common_comparison_category<_Tp>
  298. { using type = void; };
  299. template<>
  300. struct common_comparison_category<partial_ordering>
  301. { using type = partial_ordering; };
  302. template<>
  303. struct common_comparison_category<weak_ordering>
  304. { using type = weak_ordering; };
  305. template<>
  306. struct common_comparison_category<strong_ordering>
  307. { using type = strong_ordering; };
  308. template<>
  309. struct common_comparison_category<>
  310. { using type = strong_ordering; };
  311. template<typename... _Ts>
  312. using common_comparison_category_t
  313. = typename common_comparison_category<_Ts...>::type;
  314. #if __cpp_lib_concepts
  315. namespace __detail
  316. {
  317. template<typename _Tp, typename _Cat>
  318. concept __compares_as
  319. = same_as<common_comparison_category_t<_Tp, _Cat>, _Cat>;
  320. } // namespace __detail
  321. // [cmp.concept], concept three_way_comparable
  322. template<typename _Tp, typename _Cat = partial_ordering>
  323. concept three_way_comparable
  324. = __detail::__weakly_eq_cmp_with<_Tp, _Tp>
  325. && __detail::__partially_ordered_with<_Tp, _Tp>
  326. && requires(const remove_reference_t<_Tp>& __a,
  327. const remove_reference_t<_Tp>& __b)
  328. {
  329. { __a <=> __b } -> __detail::__compares_as<_Cat>;
  330. };
  331. template<typename _Tp, typename _Up, typename _Cat = partial_ordering>
  332. concept three_way_comparable_with
  333. = three_way_comparable<_Tp, _Cat>
  334. && three_way_comparable<_Up, _Cat>
  335. && common_reference_with<const remove_reference_t<_Tp>&,
  336. const remove_reference_t<_Up>&>
  337. && three_way_comparable<
  338. common_reference_t<const remove_reference_t<_Tp>&,
  339. const remove_reference_t<_Up>&>, _Cat>
  340. && __detail::__weakly_eq_cmp_with<_Tp, _Up>
  341. && __detail::__partially_ordered_with<_Tp, _Up>
  342. && requires(const remove_reference_t<_Tp>& __t,
  343. const remove_reference_t<_Up>& __u)
  344. {
  345. { __t <=> __u } -> __detail::__compares_as<_Cat>;
  346. { __u <=> __t } -> __detail::__compares_as<_Cat>;
  347. };
  348. namespace __detail
  349. {
  350. template<typename _Tp, typename _Up>
  351. using __cmp3way_res_t
  352. = decltype(std::declval<_Tp>() <=> std::declval<_Up>());
  353. // Implementation of std::compare_three_way_result.
  354. // It is undefined for a program to add specializations of
  355. // std::compare_three_way_result, so the std::compare_three_way_result_t
  356. // alias ignores std::compare_three_way_result and uses
  357. // __detail::__cmp3way_res_impl directly instead.
  358. template<typename _Tp, typename _Up>
  359. struct __cmp3way_res_impl
  360. { };
  361. template<typename _Tp, typename _Up>
  362. requires requires { typename __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; }
  363. struct __cmp3way_res_impl<_Tp, _Up>
  364. {
  365. using type = __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>;
  366. };
  367. } // namespace __detail
  368. /// [cmp.result], result of three-way comparison
  369. template<typename _Tp, typename _Up = _Tp>
  370. struct compare_three_way_result
  371. : __detail::__cmp3way_res_impl<_Tp, _Up>
  372. { };
  373. /// [cmp.result], result of three-way comparison
  374. template<typename _Tp, typename _Up = _Tp>
  375. using compare_three_way_result_t
  376. = typename __detail::__cmp3way_res_impl<_Tp, _Up>::type;
  377. namespace __detail
  378. {
  379. // BUILTIN-PTR-THREE-WAY(T, U)
  380. // This determines whether t <=> u results in a call to a built-in
  381. // operator<=> comparing pointers. It doesn't work for function pointers
  382. // (PR 93628).
  383. template<typename _Tp, typename _Up>
  384. concept __3way_builtin_ptr_cmp
  385. = requires(_Tp&& __t, _Up&& __u)
  386. { static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); }
  387. && convertible_to<_Tp, const volatile void*>
  388. && convertible_to<_Up, const volatile void*>
  389. && ! requires(_Tp&& __t, _Up&& __u)
  390. { operator<=>(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); }
  391. && ! requires(_Tp&& __t, _Up&& __u)
  392. { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); };
  393. } // namespace __detail
  394. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  395. // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks
  396. // [cmp.object], typename compare_three_way
  397. struct compare_three_way
  398. {
  399. template<typename _Tp, typename _Up>
  400. requires three_way_comparable_with<_Tp, _Up>
  401. constexpr auto
  402. operator()(_Tp&& __t, _Up&& __u) const
  403. noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>()))
  404. {
  405. if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>)
  406. {
  407. auto __pt = static_cast<const volatile void*>(__t);
  408. auto __pu = static_cast<const volatile void*>(__u);
  409. if (__builtin_is_constant_evaluated())
  410. return __pt <=> __pu;
  411. auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt);
  412. auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu);
  413. return __it <=> __iu;
  414. }
  415. else
  416. return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u);
  417. }
  418. using is_transparent = void;
  419. };
  420. namespace __cmp_cust
  421. {
  422. template<floating_point _Tp>
  423. constexpr weak_ordering
  424. __fp_weak_ordering(_Tp __e, _Tp __f)
  425. {
  426. // Returns an integer with the same sign as the argument, and magnitude
  427. // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5
  428. auto __cat = [](_Tp __fp) -> int {
  429. const int __sign = __builtin_signbit(__fp) ? -1 : 1;
  430. if (__builtin_isnormal(__fp))
  431. return (__fp == 0 ? 1 : 3) * __sign;
  432. if (__builtin_isnan(__fp))
  433. return 5 * __sign;
  434. if (int __inf = __builtin_isinf_sign(__fp))
  435. return 4 * __inf;
  436. return 2 * __sign;
  437. };
  438. auto __po = __e <=> __f;
  439. if (is_lt(__po))
  440. return weak_ordering::less;
  441. else if (is_gt(__po))
  442. return weak_ordering::greater;
  443. else if (__po == partial_ordering::equivalent)
  444. return weak_ordering::equivalent;
  445. else // unordered, at least one argument is NaN
  446. {
  447. // return -1 for negative nan, +1 for positive nan, 0 otherwise.
  448. auto __isnan_sign = [](_Tp __fp) -> int {
  449. return __builtin_isnan(__fp)
  450. ? __builtin_signbit(__fp) ? -1 : 1
  451. : 0;
  452. };
  453. auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f);
  454. if (is_eq(__ord))
  455. return weak_ordering::equivalent;
  456. else if (is_lt(__ord))
  457. return weak_ordering::less;
  458. else
  459. return weak_ordering::greater;
  460. }
  461. }
  462. template<typename _Tp, typename _Up>
  463. concept __adl_strong = requires(_Tp&& __t, _Up&& __u)
  464. {
  465. strong_ordering(strong_order(static_cast<_Tp&&>(__t),
  466. static_cast<_Up&&>(__u)));
  467. };
  468. template<typename _Tp, typename _Up>
  469. concept __adl_weak = requires(_Tp&& __t, _Up&& __u)
  470. {
  471. weak_ordering(weak_order(static_cast<_Tp&&>(__t),
  472. static_cast<_Up&&>(__u)));
  473. };
  474. template<typename _Tp, typename _Up>
  475. concept __adl_partial = requires(_Tp&& __t, _Up&& __u)
  476. {
  477. partial_ordering(partial_order(static_cast<_Tp&&>(__t),
  478. static_cast<_Up&&>(__u)));
  479. };
  480. template<typename _Ord, typename _Tp, typename _Up>
  481. concept __cmp3way = requires(_Tp&& __t, _Up&& __u, compare_three_way __c)
  482. {
  483. _Ord(__c(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)));
  484. };
  485. template<typename _Tp, typename _Up>
  486. concept __strongly_ordered
  487. = __adl_strong<_Tp, _Up>
  488. // FIXME: || floating_point<remove_reference_t<_Tp>>
  489. || __cmp3way<strong_ordering, _Tp, _Up>;
  490. class _Strong_order
  491. {
  492. template<typename _Tp, typename _Up>
  493. static constexpr bool
  494. _S_noexcept()
  495. {
  496. if constexpr (floating_point<decay_t<_Tp>>)
  497. return true;
  498. else if constexpr (__adl_strong<_Tp, _Up>)
  499. return noexcept(strong_ordering(strong_order(std::declval<_Tp>(),
  500. std::declval<_Up>())));
  501. else if constexpr (__cmp3way<strong_ordering, _Tp, _Up>)
  502. return noexcept(compare_three_way()(std::declval<_Tp>(),
  503. std::declval<_Up>()));
  504. }
  505. friend class _Weak_order;
  506. friend class _Strong_fallback;
  507. public:
  508. template<typename _Tp, typename _Up>
  509. requires __strongly_ordered<_Tp, _Up>
  510. constexpr strong_ordering
  511. operator()(_Tp&& __e, _Up&& __f) const
  512. noexcept(_S_noexcept<_Tp, _Up>())
  513. {
  514. static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
  515. /* FIXME:
  516. if constexpr (floating_point<decay_t<_Tp>>)
  517. return __cmp_cust::__fp_strong_order(__e, __f);
  518. else */ if constexpr (__adl_strong<_Tp, _Up>)
  519. return strong_ordering(strong_order(static_cast<_Tp&&>(__e),
  520. static_cast<_Up&&>(__f)));
  521. else if constexpr (__cmp3way<strong_ordering, _Tp, _Up>)
  522. return compare_three_way()(static_cast<_Tp&&>(__e),
  523. static_cast<_Up&&>(__f));
  524. }
  525. };
  526. template<typename _Tp, typename _Up>
  527. concept __weakly_ordered
  528. = floating_point<remove_reference_t<_Tp>>
  529. || __adl_weak<_Tp, _Up>
  530. || __cmp3way<weak_ordering, _Tp, _Up>
  531. || __strongly_ordered<_Tp, _Up>;
  532. class _Weak_order
  533. {
  534. template<typename _Tp, typename _Up>
  535. static constexpr bool
  536. _S_noexcept()
  537. {
  538. if constexpr (floating_point<decay_t<_Tp>>)
  539. return true;
  540. else if constexpr (__adl_weak<_Tp, _Up>)
  541. return noexcept(weak_ordering(weak_order(std::declval<_Tp>(),
  542. std::declval<_Up>())));
  543. else if constexpr (__cmp3way<weak_ordering, _Tp, _Up>)
  544. return noexcept(compare_three_way()(std::declval<_Tp>(),
  545. std::declval<_Up>()));
  546. else if constexpr (__strongly_ordered<_Tp, _Up>)
  547. return _Strong_order::_S_noexcept<_Tp, _Up>();
  548. }
  549. friend class _Partial_order;
  550. friend class _Weak_fallback;
  551. public:
  552. template<typename _Tp, typename _Up>
  553. requires __weakly_ordered<_Tp, _Up>
  554. constexpr weak_ordering
  555. operator()(_Tp&& __e, _Up&& __f) const
  556. noexcept(_S_noexcept<_Tp, _Up>())
  557. {
  558. static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
  559. if constexpr (floating_point<decay_t<_Tp>>)
  560. return __cmp_cust::__fp_weak_ordering(__e, __f);
  561. else if constexpr (__adl_weak<_Tp, _Up>)
  562. return weak_ordering(weak_order(static_cast<_Tp&&>(__e),
  563. static_cast<_Up&&>(__f)));
  564. else if constexpr (__cmp3way<weak_ordering, _Tp, _Up>)
  565. return compare_three_way()(static_cast<_Tp&&>(__e),
  566. static_cast<_Up&&>(__f));
  567. else if constexpr (__strongly_ordered<_Tp, _Up>)
  568. return _Strong_order{}(static_cast<_Tp&&>(__e),
  569. static_cast<_Up&&>(__f));
  570. }
  571. };
  572. template<typename _Tp, typename _Up>
  573. concept __partially_ordered
  574. = __adl_partial<_Tp, _Up>
  575. || __cmp3way<partial_ordering, _Tp, _Up>
  576. || __weakly_ordered<_Tp, _Up>;
  577. class _Partial_order
  578. {
  579. template<typename _Tp, typename _Up>
  580. static constexpr bool
  581. _S_noexcept()
  582. {
  583. if constexpr (__adl_partial<_Tp, _Up>)
  584. return noexcept(partial_ordering(partial_order(std::declval<_Tp>(),
  585. std::declval<_Up>())));
  586. else if constexpr (__cmp3way<partial_ordering, _Tp, _Up>)
  587. return noexcept(compare_three_way()(std::declval<_Tp>(),
  588. std::declval<_Up>()));
  589. else if constexpr (__weakly_ordered<_Tp, _Up>)
  590. return _Weak_order::_S_noexcept<_Tp, _Up>();
  591. }
  592. friend class _Partial_fallback;
  593. public:
  594. template<typename _Tp, typename _Up>
  595. requires __partially_ordered<_Tp, _Up>
  596. constexpr partial_ordering
  597. operator()(_Tp&& __e, _Up&& __f) const
  598. noexcept(_S_noexcept<_Tp, _Up>())
  599. {
  600. static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
  601. if constexpr (__adl_partial<_Tp, _Up>)
  602. return partial_ordering(partial_order(static_cast<_Tp&&>(__e),
  603. static_cast<_Up&&>(__f)));
  604. else if constexpr (__cmp3way<partial_ordering, _Tp, _Up>)
  605. return compare_three_way()(static_cast<_Tp&&>(__e),
  606. static_cast<_Up&&>(__f));
  607. else if constexpr (__weakly_ordered<_Tp, _Up>)
  608. return _Weak_order{}(static_cast<_Tp&&>(__e),
  609. static_cast<_Up&&>(__f));
  610. }
  611. };
  612. template<typename _Tp, typename _Up>
  613. concept __op_eq_lt = requires(_Tp&& __t, _Up&& __u)
  614. {
  615. { static_cast<_Tp&&>(__t) == static_cast<_Up&&>(__u) }
  616. -> convertible_to<bool>;
  617. { static_cast<_Tp&&>(__t) < static_cast<_Up&&>(__u) }
  618. -> convertible_to<bool>;
  619. };
  620. class _Strong_fallback
  621. {
  622. template<typename _Tp, typename _Up>
  623. static constexpr bool
  624. _S_noexcept()
  625. {
  626. if constexpr (__strongly_ordered<_Tp, _Up>)
  627. return _Strong_order::_S_noexcept<_Tp, _Up>();
  628. else
  629. return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>()))
  630. && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>()));
  631. }
  632. public:
  633. template<typename _Tp, typename _Up>
  634. requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up>
  635. constexpr decltype(auto)
  636. operator()(_Tp&& __e, _Up&& __f) const
  637. noexcept(_S_noexcept<_Tp, _Up>())
  638. {
  639. static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
  640. if constexpr (__strongly_ordered<_Tp, _Up>)
  641. return _Strong_order{}(static_cast<_Tp&&>(__e),
  642. static_cast<_Up&&>(__f));
  643. else if constexpr (__op_eq_lt<_Tp, _Up>)
  644. return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f)
  645. ? strong_ordering::equal
  646. : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f)
  647. ? strong_ordering::less
  648. : strong_ordering::greater;
  649. }
  650. };
  651. class _Weak_fallback
  652. {
  653. template<typename _Tp, typename _Up>
  654. static constexpr bool
  655. _S_noexcept()
  656. {
  657. if constexpr (__weakly_ordered<_Tp, _Up>)
  658. return _Weak_order::_S_noexcept<_Tp, _Up>();
  659. else
  660. return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>()))
  661. && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>()));
  662. }
  663. public:
  664. template<typename _Tp, typename _Up>
  665. requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up>
  666. constexpr decltype(auto)
  667. operator()(_Tp&& __e, _Up&& __f) const
  668. noexcept(_S_noexcept<_Tp, _Up>())
  669. {
  670. static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
  671. if constexpr (__weakly_ordered<_Tp, _Up>)
  672. return _Weak_order{}(static_cast<_Tp&&>(__e),
  673. static_cast<_Up&&>(__f));
  674. else if constexpr (__op_eq_lt<_Tp, _Up>)
  675. return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f)
  676. ? weak_ordering::equivalent
  677. : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f)
  678. ? weak_ordering::less
  679. : weak_ordering::greater;
  680. }
  681. };
  682. class _Partial_fallback
  683. {
  684. template<typename _Tp, typename _Up>
  685. static constexpr bool
  686. _S_noexcept()
  687. {
  688. if constexpr (__partially_ordered<_Tp, _Up>)
  689. return _Partial_order::_S_noexcept<_Tp, _Up>();
  690. else
  691. return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>()))
  692. && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>()));
  693. }
  694. public:
  695. template<typename _Tp, typename _Up>
  696. requires __partially_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up>
  697. constexpr decltype(auto)
  698. operator()(_Tp&& __e, _Up&& __f) const
  699. noexcept(_S_noexcept<_Tp, _Up>())
  700. {
  701. static_assert(same_as<decay_t<_Tp>, decay_t<_Up>>);
  702. if constexpr (__partially_ordered<_Tp, _Up>)
  703. return _Partial_order{}(static_cast<_Tp&&>(__e),
  704. static_cast<_Up&&>(__f));
  705. else if constexpr (__op_eq_lt<_Tp, _Up>)
  706. return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f)
  707. ? partial_ordering::equivalent
  708. : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f)
  709. ? partial_ordering::less
  710. : static_cast<_Up&&>(__f) < static_cast<_Tp&&>(__e)
  711. ? partial_ordering::greater
  712. : partial_ordering::unordered;
  713. }
  714. };
  715. } // namespace __cmp_cust
  716. // [cmp.alg], comparison algorithms
  717. inline namespace __cmp_alg
  718. {
  719. inline constexpr __cmp_cust::_Strong_order strong_order{};
  720. inline constexpr __cmp_cust::_Weak_order weak_order{};
  721. inline constexpr __cmp_cust::_Partial_order partial_order{};
  722. inline constexpr __cmp_cust::_Strong_fallback
  723. compare_strong_order_fallback{};
  724. inline constexpr __cmp_cust::_Weak_fallback
  725. compare_weak_order_fallback{};
  726. inline constexpr __cmp_cust::_Partial_fallback
  727. compare_partial_order_fallback{};
  728. }
  729. namespace __detail
  730. {
  731. // [expos.only.func] synth-three-way
  732. inline constexpr struct _Synth3way
  733. {
  734. template<typename _Tp, typename _Up>
  735. static constexpr bool
  736. _S_noexcept(const _Tp* __t = nullptr, const _Up* __u = nullptr)
  737. {
  738. if constexpr (three_way_comparable_with<_Tp, _Up>)
  739. return noexcept(*__t <=> *__u);
  740. else
  741. return noexcept(*__t < *__u) && noexcept(*__u < *__t);
  742. }
  743. template<typename _Tp, typename _Up>
  744. constexpr auto
  745. operator()(const _Tp& __t, const _Up& __u) const
  746. noexcept(_S_noexcept<_Tp, _Up>())
  747. requires requires
  748. {
  749. { __t < __u } -> __boolean_testable;
  750. { __u < __t } -> __boolean_testable;
  751. }
  752. {
  753. if constexpr (three_way_comparable_with<_Tp, _Up>)
  754. return __t <=> __u;
  755. else
  756. {
  757. if (__t < __u)
  758. return weak_ordering::less;
  759. else if (__u < __t)
  760. return weak_ordering::greater;
  761. else
  762. return weak_ordering::equivalent;
  763. }
  764. }
  765. } __synth3way = {};
  766. // [expos.only.func] synth-three-way-result
  767. template<typename _Tp, typename _Up = _Tp>
  768. using __synth3way_t
  769. = decltype(__detail::__synth3way(std::declval<_Tp&>(),
  770. std::declval<_Up&>()));
  771. } // namespace __detail
  772. #endif // concepts
  773. } // namespace std
  774. #pragma GCC visibility pop
  775. #endif // C++20
  776. #endif // _COMPARE