Home | History | Annotate | Line # | Download | only in include
      1 // -*- C++ -*-
      2 //===-------------------------- compare -----------------------------------===//
      3 //
      4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      5 // See https://llvm.org/LICENSE.txt for license information.
      6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef _LIBCPP_COMPARE
     11 #define _LIBCPP_COMPARE
     12 
     13 /*
     14     compare synopsis
     15 
     16 namespace std {
     17   // [cmp.categories], comparison category types
     18   class partial_ordering;
     19   class weak_ordering;
     20   class strong_ordering;
     21 
     22   // named comparison functions
     23   constexpr bool is_eq  (partial_ordering cmp) noexcept    { return cmp == 0; }
     24   constexpr bool is_neq (partial_ordering cmp) noexcept    { return cmp != 0; }
     25   constexpr bool is_lt  (partial_ordering cmp) noexcept { return cmp < 0; }
     26   constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; }
     27   constexpr bool is_gt  (partial_ordering cmp) noexcept { return cmp > 0; }
     28   constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; }
     29 
     30   // [cmp.common], common comparison category type
     31   template<class... Ts>
     32   struct common_comparison_category {
     33     using type = see below;
     34   };
     35   template<class... Ts>
     36     using common_comparison_category_t = typename common_comparison_category<Ts...>::type;
     37 
     38   // [cmp.alg], comparison algorithms
     39   template<class T> constexpr strong_ordering strong_order(const T& a, const T& b);
     40   template<class T> constexpr weak_ordering weak_order(const T& a, const T& b);
     41   template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);
     42 
     43   // [cmp.partialord], Class partial_ordering
     44   class partial_ordering {
     45   public:
     46     // valid values
     47     static const partial_ordering less;
     48     static const partial_ordering equivalent;
     49     static const partial_ordering greater;
     50     static const partial_ordering unordered;
     51 
     52     // comparisons
     53     friend constexpr bool operator==(partial_ordering v, unspecified) noexcept;
     54     friend constexpr bool operator==(partial_ordering v, partial_ordering w) noexcept = default;
     55     friend constexpr bool operator< (partial_ordering v, unspecified) noexcept;
     56     friend constexpr bool operator> (partial_ordering v, unspecified) noexcept;
     57     friend constexpr bool operator<=(partial_ordering v, unspecified) noexcept;
     58     friend constexpr bool operator>=(partial_ordering v, unspecified) noexcept;
     59     friend constexpr bool operator< (unspecified, partial_ordering v) noexcept;
     60     friend constexpr bool operator> (unspecified, partial_ordering v) noexcept;
     61     friend constexpr bool operator<=(unspecified, partial_ordering v) noexcept;
     62     friend constexpr bool operator>=(unspecified, partial_ordering v) noexcept;
     63     friend constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept;
     64     friend constexpr partial_ordering operator<=>(unspecified, partial_ordering v) noexcept;
     65   };
     66 
     67   // [cmp.weakord], Class weak_ordering
     68   class weak_ordering {
     69   public:
     70     // valid values
     71     static const weak_ordering less;
     72     static const weak_ordering equivalent;
     73     static const weak_ordering greater;
     74 
     75     // conversions
     76     constexpr operator partial_ordering() const noexcept;
     77 
     78     // comparisons
     79     friend constexpr bool operator==(weak_ordering v, unspecified) noexcept;
     80     friend constexpr bool operator==(weak_ordering v, weak_ordering w) noexcept = default;
     81     friend constexpr bool operator< (weak_ordering v, unspecified) noexcept;
     82     friend constexpr bool operator> (weak_ordering v, unspecified) noexcept;
     83     friend constexpr bool operator<=(weak_ordering v, unspecified) noexcept;
     84     friend constexpr bool operator>=(weak_ordering v, unspecified) noexcept;
     85     friend constexpr bool operator< (unspecified, weak_ordering v) noexcept;
     86     friend constexpr bool operator> (unspecified, weak_ordering v) noexcept;
     87     friend constexpr bool operator<=(unspecified, weak_ordering v) noexcept;
     88     friend constexpr bool operator>=(unspecified, weak_ordering v) noexcept;
     89     friend constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept;
     90     friend constexpr weak_ordering operator<=>(unspecified, weak_ordering v) noexcept;
     91   };
     92 
     93   // [cmp.strongord], Class strong_ordering
     94   class strong_ordering {
     95   public:
     96     // valid values
     97     static const strong_ordering less;
     98     static const strong_ordering equal;
     99     static const strong_ordering equivalent;
    100     static const strong_ordering greater;
    101 
    102     // conversions
    103     constexpr operator partial_ordering() const noexcept;
    104     constexpr operator weak_ordering() const noexcept;
    105 
    106     // comparisons
    107     friend constexpr bool operator==(strong_ordering v, unspecified) noexcept;
    108     friend constexpr bool operator==(strong_ordering v, strong_ordering w) noexcept = default;
    109     friend constexpr bool operator< (strong_ordering v, unspecified) noexcept;
    110     friend constexpr bool operator> (strong_ordering v, unspecified) noexcept;
    111     friend constexpr bool operator<=(strong_ordering v, unspecified) noexcept;
    112     friend constexpr bool operator>=(strong_ordering v, unspecified) noexcept;
    113     friend constexpr bool operator< (unspecified, strong_ordering v) noexcept;
    114     friend constexpr bool operator> (unspecified, strong_ordering v) noexcept;
    115     friend constexpr bool operator<=(unspecified, strong_ordering v) noexcept;
    116     friend constexpr bool operator>=(unspecified, strong_ordering v) noexcept;
    117     friend constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept;
    118     friend constexpr strong_ordering operator<=>(unspecified, strong_ordering v) noexcept;
    119   };
    120 }
    121 */
    122 
    123 #include <__config>
    124 #include <type_traits>
    125 
    126 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
    127 #pragma GCC system_header
    128 #endif
    129 
    130 _LIBCPP_BEGIN_NAMESPACE_STD
    131 
    132 #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR)
    133 // exposition only
    134 enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char {
    135   __zero = 0,
    136   __equal = __zero,
    137   __equiv = __equal,
    138   __nonequal = 1,
    139   __nonequiv = __nonequal
    140 };
    141 
    142 enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {
    143   __less = -1,
    144   __greater = 1
    145 };
    146 
    147 enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
    148   __unordered = -127
    149 };
    150 
    151 class partial_ordering;
    152 class weak_ordering;
    153 class strong_ordering;
    154 
    155 template<class _Tp, class... _Args>
    156 inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...);
    157 
    158 struct _CmpUnspecifiedParam {
    159   _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL
    160   _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
    161 
    162   template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>>
    163   _CmpUnspecifiedParam(_Tp) = delete;
    164 };
    165 
    166 class partial_ordering {
    167   using _ValueT = signed char;
    168 
    169   _LIBCPP_INLINE_VISIBILITY
    170   explicit constexpr partial_ordering(_EqResult __v) noexcept
    171       : __value_(_ValueT(__v)) {}
    172 
    173   _LIBCPP_INLINE_VISIBILITY
    174   explicit constexpr partial_ordering(_OrdResult __v) noexcept
    175       : __value_(_ValueT(__v)) {}
    176 
    177   _LIBCPP_INLINE_VISIBILITY
    178   explicit constexpr partial_ordering(_NCmpResult __v) noexcept
    179       : __value_(_ValueT(__v)) {}
    180 
    181   constexpr bool __is_ordered() const noexcept {
    182     return __value_ != _ValueT(_NCmpResult::__unordered);
    183   }
    184 public:
    185   // valid values
    186   static const partial_ordering less;
    187   static const partial_ordering equivalent;
    188   static const partial_ordering greater;
    189   static const partial_ordering unordered;
    190 
    191   // comparisons
    192   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
    193 
    194   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    195     return __v.__is_ordered() && __v.__value_ == 0;
    196   }
    197 
    198   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept {
    199     return __v.__is_ordered() && __v.__value_ < 0;
    200   }
    201 
    202   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
    203     return __v.__is_ordered() && __v.__value_ <= 0;
    204   }
    205 
    206   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
    207     return __v.__is_ordered() && __v.__value_ > 0;
    208   }
    209 
    210   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
    211     return __v.__is_ordered() && __v.__value_ >= 0;
    212   }
    213 
    214   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
    215     return __v.__is_ordered() && 0 < __v.__value_;
    216   }
    217 
    218   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
    219     return __v.__is_ordered() && 0 <= __v.__value_;
    220   }
    221 
    222   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
    223     return __v.__is_ordered() && 0 > __v.__value_;
    224   }
    225 
    226   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
    227     return __v.__is_ordered() && 0 >= __v.__value_;
    228   }
    229 
    230   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept  {
    231     return __v;
    232   }
    233 
    234   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept  {
    235     return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);
    236   }
    237 private:
    238   _ValueT __value_;
    239 };
    240 
    241 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less);
    242 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv);
    243 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater);
    244 _LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered);
    245 
    246 class weak_ordering {
    247   using _ValueT = signed char;
    248 
    249   _LIBCPP_INLINE_VISIBILITY
    250   explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
    251   _LIBCPP_INLINE_VISIBILITY
    252   explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}
    253 
    254 public:
    255   static const weak_ordering less;
    256   static const weak_ordering equivalent;
    257   static const weak_ordering greater;
    258 
    259   _LIBCPP_INLINE_VISIBILITY
    260   constexpr operator partial_ordering() const noexcept {
    261     return __value_ == 0 ? partial_ordering::equivalent
    262         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
    263   }
    264 
    265   // comparisons
    266   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
    267 
    268   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    269     return __v.__value_ == 0;
    270   }
    271 
    272   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    273     return __v.__value_ < 0;
    274   }
    275 
    276   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    277     return __v.__value_ <= 0;
    278   }
    279 
    280   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    281     return __v.__value_ > 0;
    282   }
    283 
    284   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    285     return __v.__value_ >= 0;
    286   }
    287 
    288   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    289     return 0 < __v.__value_;
    290   }
    291 
    292   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    293     return 0 <= __v.__value_;
    294   }
    295 
    296   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    297     return 0 > __v.__value_;
    298   }
    299 
    300   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    301     return 0 >= __v.__value_;
    302   }
    303 
    304   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {
    305     return __v;
    306   }
    307 
    308   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept {
    309     return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);
    310   }
    311 
    312 private:
    313   _ValueT __value_;
    314 };
    315 
    316 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less);
    317 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv);
    318 _LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater);
    319 class strong_ordering {
    320   using _ValueT = signed char;
    321 
    322   _LIBCPP_INLINE_VISIBILITY
    323   explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}
    324   _LIBCPP_INLINE_VISIBILITY
    325   explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__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   _LIBCPP_INLINE_VISIBILITY
    335   constexpr operator partial_ordering() const noexcept {
    336     return __value_ == 0 ? partial_ordering::equivalent
    337         : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);
    338   }
    339 
    340   _LIBCPP_INLINE_VISIBILITY
    341   constexpr operator weak_ordering() const noexcept {
    342     return __value_ == 0 ? weak_ordering::equivalent
    343         : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
    344   }
    345 
    346   // comparisons
    347   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
    348 
    349   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    350     return __v.__value_ == 0;
    351   }
    352 
    353   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    354     return __v.__value_ < 0;
    355   }
    356 
    357   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    358     return __v.__value_ <= 0;
    359   }
    360 
    361   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    362     return __v.__value_ > 0;
    363   }
    364 
    365   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    366     return __v.__value_ >= 0;
    367   }
    368 
    369   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    370     return 0 < __v.__value_;
    371   }
    372 
    373   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    374     return 0 <= __v.__value_;
    375   }
    376 
    377   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    378     return 0 > __v.__value_;
    379   }
    380 
    381   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    382     return 0 >= __v.__value_;
    383   }
    384 
    385   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {
    386     return __v;
    387   }
    388 
    389   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept {
    390     return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);
    391   }
    392 
    393 private:
    394   _ValueT __value_;
    395 };
    396 
    397 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less);
    398 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal);
    399 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv);
    400 _LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater);
    401 
    402 // named comparison functions
    403 _LIBCPP_INLINE_VISIBILITY
    404 constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }
    405 
    406 _LIBCPP_INLINE_VISIBILITY
    407 constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }
    408 
    409 _LIBCPP_INLINE_VISIBILITY
    410 constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }
    411 
    412 _LIBCPP_INLINE_VISIBILITY
    413 constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }
    414 
    415 namespace __comp_detail {
    416 
    417 enum _ClassifyCompCategory : unsigned{
    418   _None,
    419   _PartialOrd,
    420   _WeakOrd,
    421   _StrongOrd,
    422   _CCC_Size
    423 };
    424 
    425 template <class _Tp>
    426 _LIBCPP_INLINE_VISIBILITY
    427 constexpr _ClassifyCompCategory __type_to_enum() noexcept {
    428   if (is_same_v<_Tp, partial_ordering>)
    429     return _PartialOrd;
    430   if (is_same_v<_Tp, weak_ordering>)
    431     return _WeakOrd;
    432   if (is_same_v<_Tp, strong_ordering>)
    433     return _StrongOrd;
    434   return _None;
    435 }
    436 
    437 template <size_t _Size>
    438 constexpr _ClassifyCompCategory
    439 __compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) {
    440   int __seen[_CCC_Size] = {};
    441   for (auto __type : __types)
    442     ++__seen[__type];
    443   if (__seen[_None])
    444     return _None;
    445   if (__seen[_PartialOrd])
    446     return _PartialOrd;
    447   if (__seen[_WeakOrd])
    448     return _WeakOrd;
    449   return _StrongOrd;
    450 }
    451 
    452 template <class ..._Ts>
    453 constexpr auto __get_comp_type() {
    454   using _CCC = _ClassifyCompCategory;
    455   constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...};
    456   constexpr _CCC _Cat = __compute_comp_type(__type_kinds);
    457   if constexpr (_Cat == _None)
    458     return void();
    459   else if constexpr (_Cat == _PartialOrd)
    460     return partial_ordering::equivalent;
    461   else if constexpr (_Cat == _WeakOrd)
    462     return weak_ordering::equivalent;
    463   else if constexpr (_Cat == _StrongOrd)
    464     return strong_ordering::equivalent;
    465   else
    466     static_assert(_Cat != _Cat, "unhandled case");
    467 }
    468 } // namespace __comp_detail
    469 
    470 // [cmp.common], common comparison category type
    471 template<class... _Ts>
    472 struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
    473   using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
    474 };
    475 
    476 template<class... _Ts>
    477 using common_comparison_category_t = typename common_comparison_category<_Ts...>::type;
    478 
    479 // [cmp.alg], comparison algorithms
    480 // TODO: unimplemented
    481 template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs);
    482 template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs);
    483 template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs);
    484 
    485 #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR)
    486 
    487 _LIBCPP_END_NAMESPACE_STD
    488 
    489 #endif // _LIBCPP_COMPARE
    490