Home | History | Annotate | Download | only in include
      1 // -*- C++ -*-
      2 //===-------------------------- compare -----------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_COMPARE
     12 #define _LIBCPP_COMPARE
     13 
     14 /*
     15     compare synopsis
     16 
     17 namespace std {
     18   // [cmp.categories], comparison category types
     19   class weak_equality;
     20   class strong_equality;
     21   class partial_ordering;
     22   class weak_ordering;
     23   class strong_ordering;
     24 
     25   // named comparison functions
     26   constexpr bool is_eq  (weak_equality cmp) noexcept    { return cmp == 0; }
     27   constexpr bool is_neq (weak_equality cmp) noexcept    { return cmp != 0; }
     28   constexpr bool is_lt  (partial_ordering cmp) noexcept { return cmp < 0; }
     29   constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; }
     30   constexpr bool is_gt  (partial_ordering cmp) noexcept { return cmp > 0; }
     31   constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; }
     32 
     33   // [cmp.common], common comparison category type
     34   template<class... Ts>
     35   struct common_comparison_category {
     36     using type = see below;
     37   };
     38   template<class... Ts>
     39     using common_comparison_category_t = typename common_comparison_category<Ts...>::type;
     40 
     41   // [cmp.alg], comparison algorithms
     42   template<class T> constexpr strong_ordering strong_order(const T& a, const T& b);
     43   template<class T> constexpr weak_ordering weak_order(const T& a, const T& b);
     44   template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);
     45   template<class T> constexpr strong_equality strong_equal(const T& a, const T& b);
     46   template<class T> constexpr weak_equality weak_equal(const T& a, const T& b);
     47 }
     48 */
     49 
     50 #include <__config>
     51 #include <type_traits>
     52 #include <array>
     53 
     54 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
     55 #pragma GCC system_header
     56 #endif
     57 
     58 _LIBCPP_BEGIN_NAMESPACE_STD
     59 
     60 #if _LIBCPP_STD_VER > 17
     61 
     62 // exposition only
     63 enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char {
     64   __zero = 0,
     65   __equal = __zero,
     66   __equiv = __equal,
     67   __nonequal = 1,
     68   __nonequiv = __nonequal
     69 };
     70 
     71 enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {
     72   __less = -1,
     73   __greater = 1
     74 };
     75 
     76 enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
     77   __unordered = -127
     78 };
     79 
     80 struct _CmpUnspecifiedType;
     81 using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
     82 
     83 class  weak_equality {
     84   _LIBCPP_INLINE_VISIBILITY
     85   constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}
     86 
     87 public:
     88   static const weak_equality equivalent;
     89   static const weak_equality nonequivalent;
     90 
     91   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;
     92   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept;
     93   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;
     94   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept;
     95 
     96 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
     97   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;
     98   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept;
     99 #endif
    100 
    101 private:
    102   _EqResult __value_;
    103 };
    104 
    105 _LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv);
    106 _LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv);
    107 
    108 _LIBCPP_INLINE_VISIBILITY
    109 inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {
    110   return __v.__value_ == _EqResult::__zero;
    111 }
    112 
    113 _LIBCPP_INLINE_VISIBILITY
    114 inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept {
    115   return __v.__value_ == _EqResult::__zero;
    116 }
    117 
    118 _LIBCPP_INLINE_VISIBILITY
    119 inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {
    120   return __v.__value_ != _EqResult::__zero;
    121 }
    122 
    123 _LIBCPP_INLINE_VISIBILITY
    124 inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept {
    125   return __v.__value_ != _EqResult::__zero;
    126 }
    127 
    128 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    129 _LIBCPP_INLINE_VISIBILITY
    130 inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {
    131   return __v;
    132 }
    133 
    134 _LIBCPP_INLINE_VISIBILITY
    135 inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept {
    136   return __v;
    137 }
    138 #endif
    139 
    140 class strong_equality {
    141   _LIBCPP_INLINE_VISIBILITY
    142   explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}
    143 
    144 public:
    145   static const strong_equality equal;
    146   static const strong_equality nonequal;
    147   static const strong_equality equivalent;
    148   static const strong_equality nonequivalent;
    149 
    150   // conversion
    151   _LIBCPP_INLINE_VISIBILITY constexpr operator weak_equality() const noexcept {
    152     return __value_ == _EqResult::__zero ? weak_equality::equivalent
    153           : weak_equality::nonequivalent;
    154   }
    155 
    156   // comparisons
    157   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;
    158   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;
    159   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept;
    160   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept;
    161 
    162 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    163   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;
    164   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept;
    165 #endif
    166 private:
    167   _EqResult __value_;
    168 };
    169 
    170 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equal(_EqResult::__equal);
    171 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal);
    172 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv);
    173 _LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv);
    174 
    175 _LIBCPP_INLINE_VISIBILITY
    176 constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {
    177   return __v.__value_ == _EqResult::__zero;
    178 }
    179 
    180 _LIBCPP_INLINE_VISIBILITY
    181 constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept {
    182   return __v.__value_ == _EqResult::__zero;
    183 }
    184 
    185 _LIBCPP_INLINE_VISIBILITY
    186 constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {
    187   return __v.__value_ != _EqResult::__zero;
    188 }
    189 
    190 _LIBCPP_INLINE_VISIBILITY
    191 constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept {
    192   return __v.__value_ != _EqResult::__zero;
    193 }
    194 
    195 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    196 _LIBCPP_INLINE_VISIBILITY
    197 constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {
    198   return __v;
    199 }
    200 
    201 _LIBCPP_INLINE_VISIBILITY
    202 constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept {
    203   return __v;
    204 }
    205 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    206 
    207 class partial_ordering {
    208   using _ValueT = signed char;
    209 
    210   _LIBCPP_INLINE_VISIBILITY
    211   explicit constexpr partial_ordering(_EqResult __v) noexcept
    212       : __value_(_ValueT(__v)) {}
    213 
    214   _LIBCPP_INLINE_VISIBILITY
    215   explicit constexpr partial_ordering(_OrdResult __v) noexcept
    216       : __value_(_ValueT(__v)) {}
    217 
    218   _LIBCPP_INLINE_VISIBILITY
    219   explicit constexpr partial_ordering(_NCmpResult __v) noexcept
    220       : __value_(_ValueT(__v)) {}
    221 
    222   constexpr bool __is_ordered() const noexcept {
    223     return __value_ != _ValueT(_NCmpResult::__unordered);
    224   }
    225 public:
    226   // valid values
    227   static const partial_ordering less;
    228   static const partial_ordering equivalent;
    229   static const partial_ordering greater;
    230   static const partial_ordering unordered;
    231 
    232   // conversion
    233   constexpr operator weak_equality() const noexcept {
    234     return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;
    235   }
    236 
    237   // comparisons
    238   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    239   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    240   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    241   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    242   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    243   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    244   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    245   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    246   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    247   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    248   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    249   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    250 
    251 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    252   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
    253   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
    254 #endif
    255 
    256 private:
    257   _ValueT __value_;
    258 };
    259 
    260 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
    261 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
    262 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
    263 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
    264 
    265 _LIBCPP_INLINE_VISIBILITY
    266 constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    267   return __v.__is_ordered() && __v.__value_ == 0;
    268 }
    269 _LIBCPP_INLINE_VISIBILITY
    270 constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    271   return __v.__is_ordered() && __v.__value_ < 0;
    272 }
    273 _LIBCPP_INLINE_VISIBILITY
    274 constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    275   return __v.__is_ordered() && __v.__value_ <= 0;
    276 }
    277 _LIBCPP_INLINE_VISIBILITY
    278 constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    279   return __v.__is_ordered() && __v.__value_ > 0;
    280 }
    281 _LIBCPP_INLINE_VISIBILITY
    282 constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    283   return __v.__is_ordered() && __v.__value_ >= 0;
    284 }
    285 
    286 _LIBCPP_INLINE_VISIBILITY
    287 constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    288   return __v.__is_ordered() && 0 == __v.__value_;
    289 }
    290 _LIBCPP_INLINE_VISIBILITY
    291 constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    292   return __v.__is_ordered() && 0 < __v.__value_;
    293 }
    294 _LIBCPP_INLINE_VISIBILITY
    295 constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    296   return __v.__is_ordered() && 0 <= __v.__value_;
    297 }
    298 _LIBCPP_INLINE_VISIBILITY
    299 constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    300   return __v.__is_ordered() && 0 > __v.__value_;
    301 }
    302 _LIBCPP_INLINE_VISIBILITY
    303 constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    304   return __v.__is_ordered() && 0 >= __v.__value_;
    305 }
    306 
    307 _LIBCPP_INLINE_VISIBILITY
    308 constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    309   return !__v.__is_ordered() || __v.__value_ != 0;
    310 }
    311 _LIBCPP_INLINE_VISIBILITY
    312 constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    313   return !__v.__is_ordered() || __v.__value_ != 0;
    314 }
    315 
    316 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    317 _LIBCPP_INLINE_VISIBILITY
    318 constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    319   return __v;
    320 }
    321 _LIBCPP_INLINE_VISIBILITY
    322 constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept {
    323   return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
    324 }
    325 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    326 
    327 class weak_ordering {
    328   using _ValueT = signed char;
    329 
    330   _LIBCPP_INLINE_VISIBILITY
    331   explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
    332   _LIBCPP_INLINE_VISIBILITY
    333   explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
    334 
    335 public:
    336   static const weak_ordering less;
    337   static const weak_ordering equivalent;
    338   static const weak_ordering greater;
    339 
    340   // conversions
    341   _LIBCPP_INLINE_VISIBILITY
    342   constexpr operator weak_equality() const noexcept {
    343     return __value_ == 0 ? weak_equality::equivalent
    344                          : weak_equality::nonequivalent;
    345   }
    346 
    347   _LIBCPP_INLINE_VISIBILITY
    348   constexpr operator partial_ordering() const noexcept {
    349     return __value_ == 0 ? partial_ordering::equivalent
    350         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
    351   }
    352 
    353   // comparisons
    354   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    355   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    356   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    357   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    358   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    359   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    360   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    361   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    362   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    363   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    364   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    365   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    366 
    367 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    368   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
    369   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
    370 #endif
    371 
    372 private:
    373   _ValueT __value_;
    374 };
    375 
    376 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
    377 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
    378 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
    379 
    380 _LIBCPP_INLINE_VISIBILITY
    381 constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    382   return __v.__value_ == 0;
    383 }
    384 _LIBCPP_INLINE_VISIBILITY
    385 constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    386   return __v.__value_ != 0;
    387 }
    388 _LIBCPP_INLINE_VISIBILITY
    389 constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    390   return __v.__value_ < 0;
    391 }
    392 _LIBCPP_INLINE_VISIBILITY
    393 constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    394   return __v.__value_ <= 0;
    395 }
    396 _LIBCPP_INLINE_VISIBILITY
    397 constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    398   return __v.__value_ > 0;
    399 }
    400 _LIBCPP_INLINE_VISIBILITY
    401 constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    402   return __v.__value_ >= 0;
    403 }
    404 _LIBCPP_INLINE_VISIBILITY
    405 constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    406   return 0 == __v.__value_;
    407 }
    408 _LIBCPP_INLINE_VISIBILITY
    409 constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    410   return 0 != __v.__value_;
    411 }
    412 _LIBCPP_INLINE_VISIBILITY
    413 constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    414   return 0 < __v.__value_;
    415 }
    416 _LIBCPP_INLINE_VISIBILITY
    417 constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    418   return 0 <= __v.__value_;
    419 }
    420 _LIBCPP_INLINE_VISIBILITY
    421 constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    422   return 0 > __v.__value_;
    423 }
    424 _LIBCPP_INLINE_VISIBILITY
    425 constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    426   return 0 >= __v.__value_;
    427 }
    428 
    429 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    430 _LIBCPP_INLINE_VISIBILITY
    431 constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    432   return __v;
    433 }
    434 _LIBCPP_INLINE_VISIBILITY
    435 constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    436   return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
    437 }
    438 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    439 
    440 class strong_ordering {
    441   using _ValueT = signed char;
    442 
    443   _LIBCPP_INLINE_VISIBILITY
    444   explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
    445   _LIBCPP_INLINE_VISIBILITY
    446   explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
    447 
    448 public:
    449   static const strong_ordering less;
    450   static const strong_ordering equal;
    451   static const strong_ordering equivalent;
    452   static const strong_ordering greater;
    453 
    454   // conversions
    455   _LIBCPP_INLINE_VISIBILITY
    456   constexpr operator weak_equality() const noexcept {
    457     return __value_ == 0 ? weak_equality::equivalent
    458                          : weak_equality::nonequivalent;
    459   }
    460 
    461   _LIBCPP_INLINE_VISIBILITY
    462   constexpr operator strong_equality() const noexcept {
    463     return __value_ == 0 ? strong_equality::equal
    464                          : strong_equality::nonequal;
    465   }
    466 
    467   _LIBCPP_INLINE_VISIBILITY
    468   constexpr operator partial_ordering() const noexcept {
    469     return __value_ == 0 ? partial_ordering::equivalent
    470         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
    471   }
    472 
    473   _LIBCPP_INLINE_VISIBILITY
    474   constexpr operator weak_ordering() const noexcept {
    475     return __value_ == 0 ? weak_ordering::equivalent
    476         : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
    477   }
    478 
    479   // comparisons
    480   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    481   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    482   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    483   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    484   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    485   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    486   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    487   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    488   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    489   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    490   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    491   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    492 
    493 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    494   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
    495   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
    496 #endif
    497 
    498 private:
    499   _ValueT __value_;
    500 };
    501 
    502 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
    503 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
    504 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
    505 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
    506 
    507 _LIBCPP_INLINE_VISIBILITY
    508 constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    509   return __v.__value_ == 0;
    510 }
    511 _LIBCPP_INLINE_VISIBILITY
    512 constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    513   return __v.__value_ != 0;
    514 }
    515 _LIBCPP_INLINE_VISIBILITY
    516 constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    517   return __v.__value_ < 0;
    518 }
    519 _LIBCPP_INLINE_VISIBILITY
    520 constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    521   return __v.__value_ <= 0;
    522 }
    523 _LIBCPP_INLINE_VISIBILITY
    524 constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    525   return __v.__value_ > 0;
    526 }
    527 _LIBCPP_INLINE_VISIBILITY
    528 constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    529   return __v.__value_ >= 0;
    530 }
    531 _LIBCPP_INLINE_VISIBILITY
    532 constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    533   return 0 == __v.__value_;
    534 }
    535 _LIBCPP_INLINE_VISIBILITY
    536 constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    537   return 0 != __v.__value_;
    538 }
    539 _LIBCPP_INLINE_VISIBILITY
    540 constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    541   return 0 < __v.__value_;
    542 }
    543 _LIBCPP_INLINE_VISIBILITY
    544 constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    545   return 0 <= __v.__value_;
    546 }
    547 _LIBCPP_INLINE_VISIBILITY
    548 constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    549   return 0 > __v.__value_;
    550 }
    551 _LIBCPP_INLINE_VISIBILITY
    552 constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    553   return 0 >= __v.__value_;
    554 }
    555 
    556 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    557 _LIBCPP_INLINE_VISIBILITY
    558 constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    559   return __v;
    560 }
    561 _LIBCPP_INLINE_VISIBILITY
    562 constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    563   return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
    564 }
    565 #endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
    566 
    567 // named comparison functions
    568 _LIBCPP_INLINE_VISIBILITY
    569 constexpr bool is_eq(weak_equality __cmp) noexcept    { return __cmp == 0; }
    570 
    571 _LIBCPP_INLINE_VISIBILITY
    572 constexpr bool is_neq(weak_equality __cmp) noexcept    { return __cmp != 0; }
    573 
    574 _LIBCPP_INLINE_VISIBILITY
    575 constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
    576 
    577 _LIBCPP_INLINE_VISIBILITY
    578 constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
    579 
    580 _LIBCPP_INLINE_VISIBILITY
    581 constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
    582 
    583 _LIBCPP_INLINE_VISIBILITY
    584 constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
    585 
    586 namespace __comp_detail {
    587 
    588 enum _ClassifyCompCategory : unsigned{
    589   _None,
    590   _WeakEq,
    591   _StrongEq,
    592   _PartialOrd,
    593   _WeakOrd,
    594   _StrongOrd,
    595   _CCC_Size
    596 };
    597 
    598 template <class _Tp>
    599 _LIBCPP_INLINE_VISIBILITY
    600 constexpr _ClassifyCompCategory __type_to_enum() noexcept {
    601   if (is_same_v<_Tp, weak_equality>)
    602     return _WeakEq;
    603   if (is_same_v<_Tp, strong_equality>)
    604     return _StrongEq;
    605   if (is_same_v<_Tp, partial_ordering>)
    606     return _PartialOrd;
    607   if (is_same_v<_Tp, weak_ordering>)
    608     return _WeakOrd;
    609   if (is_same_v<_Tp, strong_ordering>)
    610     return _StrongOrd;
    611   return _None;
    612 }
    613 
    614 template <size_t _Size>
    615 constexpr _ClassifyCompCategory
    616 __compute_comp_type(std::array<_ClassifyCompCategory, _Size> __types) {
    617   std::array<int, _CCC_Size> __seen = {};
    618   for (auto __type : __types)
    619     ++__seen[__type];
    620   if (__seen[_None])
    621     return _None;
    622   if (__seen[_WeakEq])
    623     return _WeakEq;
    624   if (__seen[_StrongEq] && (__seen[_PartialOrd] || __seen[_WeakOrd]))
    625     return _WeakEq;
    626   if (__seen[_StrongEq])
    627     return _StrongEq;
    628   if (__seen[_PartialOrd])
    629     return _PartialOrd;
    630   if (__seen[_WeakOrd])
    631     return _WeakOrd;
    632   return _StrongOrd;
    633 }
    634 
    635 template <class ..._Ts>
    636 constexpr auto __get_comp_type() {
    637   using _CCC = _ClassifyCompCategory;
    638   constexpr array<_CCC, sizeof...(_Ts)> __type_kinds{{__comp_detail::__type_to_enum<_Ts>()...}};
    639   constexpr _CCC _Cat = sizeof...(_Ts) == 0 ? _StrongOrd
    640       : __compute_comp_type(__type_kinds);
    641   if constexpr (_Cat == _None)
    642     return void();
    643   else if constexpr (_Cat == _WeakEq)
    644     return weak_equality::equivalent;
    645   else if constexpr (_Cat == _StrongEq)
    646     return strong_equality::equivalent;
    647   else if constexpr (_Cat == _PartialOrd)
    648     return partial_ordering::equivalent;
    649   else if constexpr (_Cat == _WeakOrd)
    650     return weak_ordering::equivalent;
    651   else if constexpr (_Cat == _StrongOrd)
    652     return strong_ordering::equivalent;
    653   else
    654     static_assert(_Cat != _Cat, "unhandled case");
    655 }
    656 } // namespace __comp_detail
    657 
    658 // [cmp.common], common comparison category type
    659 template<class... _Ts>
    660 struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
    661   using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
    662 };
    663 
    664 template<class... _Ts>
    665 using common_comparison_category_t = typename common_comparison_category<_Ts...>::type;
    666 
    667 // [cmp.alg], comparison algorithms
    668 // TODO: unimplemented
    669 template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs);
    670 template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs);
    671 template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs);
    672 template<class _Tp> constexpr strong_equality strong_equal(const _Tp& __lhs, const _Tp& __rhs);
    673 template<class _Tp> constexpr weak_equality weak_equal(const _Tp& __lhs, const _Tp& __rhs);
    674 
    675 #endif // _LIBCPP_STD_VER > 17
    676 
    677 _LIBCPP_END_NAMESPACE_STD
    678 
    679 #endif // _LIBCPP_COMPARE
    680