1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric 9349cc55cSDimitry Andric #ifndef _LIBCPP___COMPARE_ORDERING_H 10349cc55cSDimitry Andric #define _LIBCPP___COMPARE_ORDERING_H 11349cc55cSDimitry Andric 12349cc55cSDimitry Andric #include <__config> 13bdd1243dSDimitry Andric #include <__type_traits/enable_if.h> 14bdd1243dSDimitry Andric #include <__type_traits/is_same.h> 15349cc55cSDimitry Andric 16349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 17349cc55cSDimitry Andric # pragma GCC system_header 18349cc55cSDimitry Andric #endif 19349cc55cSDimitry Andric 20349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 21349cc55cSDimitry Andric 2206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric // exposition only 25*cb14a3feSDimitry Andric enum class _OrdResult : signed char { __less = -1, __equiv = 0, __greater = 1 }; 26349cc55cSDimitry Andric 27*cb14a3feSDimitry Andric enum class _NCmpResult : signed char { __unordered = -127 }; 28349cc55cSDimitry Andric 29349cc55cSDimitry Andric class partial_ordering; 30349cc55cSDimitry Andric class weak_ordering; 31349cc55cSDimitry Andric class strong_ordering; 32349cc55cSDimitry Andric 33349cc55cSDimitry Andric template <class _Tp, class... _Args> 34349cc55cSDimitry Andric inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); 35349cc55cSDimitry Andric 36349cc55cSDimitry Andric struct _CmpUnspecifiedParam { _CmpUnspecifiedParam_CmpUnspecifiedParam37*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} 38349cc55cSDimitry Andric 39349cc55cSDimitry Andric template <class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>> 40349cc55cSDimitry Andric _CmpUnspecifiedParam(_Tp) = delete; 41349cc55cSDimitry Andric }; 42349cc55cSDimitry Andric 43349cc55cSDimitry Andric class partial_ordering { 44349cc55cSDimitry Andric using _ValueT = signed char; 45349cc55cSDimitry Andric partial_ordering(_OrdResult __v)46*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit constexpr partial_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 47349cc55cSDimitry Andric partial_ordering(_NCmpResult __v)48*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit constexpr partial_ordering(_NCmpResult __v) noexcept : __value_(_ValueT(__v)) {} 49349cc55cSDimitry Andric __is_ordered()50*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __is_ordered() const noexcept { 51349cc55cSDimitry Andric return __value_ != _ValueT(_NCmpResult::__unordered); 52349cc55cSDimitry Andric } 53*cb14a3feSDimitry Andric 54349cc55cSDimitry Andric public: 55349cc55cSDimitry Andric // valid values 56349cc55cSDimitry Andric static const partial_ordering less; 57349cc55cSDimitry Andric static const partial_ordering equivalent; 58349cc55cSDimitry Andric static const partial_ordering greater; 59349cc55cSDimitry Andric static const partial_ordering unordered; 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric // comparisons 62*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; 63349cc55cSDimitry Andric 64*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 65349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ == 0; 66349cc55cSDimitry Andric } 67349cc55cSDimitry Andric 68*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 69349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ < 0; 70349cc55cSDimitry Andric } 71349cc55cSDimitry Andric 72*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 73349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ <= 0; 74349cc55cSDimitry Andric } 75349cc55cSDimitry Andric 76*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 77349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ > 0; 78349cc55cSDimitry Andric } 79349cc55cSDimitry Andric 80*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 81349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ >= 0; 82349cc55cSDimitry Andric } 83349cc55cSDimitry Andric 84*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 85349cc55cSDimitry Andric return __v.__is_ordered() && 0 < __v.__value_; 86349cc55cSDimitry Andric } 87349cc55cSDimitry Andric 88*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 89349cc55cSDimitry Andric return __v.__is_ordered() && 0 <= __v.__value_; 90349cc55cSDimitry Andric } 91349cc55cSDimitry Andric 92*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 93349cc55cSDimitry Andric return __v.__is_ordered() && 0 > __v.__value_; 94349cc55cSDimitry Andric } 95349cc55cSDimitry Andric 96*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 97349cc55cSDimitry Andric return __v.__is_ordered() && 0 >= __v.__value_; 98349cc55cSDimitry Andric } 99349cc55cSDimitry Andric 100*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering 101*cb14a3feSDimitry Andric operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 102349cc55cSDimitry Andric return __v; 103349cc55cSDimitry Andric } 104349cc55cSDimitry Andric 105*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr partial_ordering 106*cb14a3feSDimitry Andric operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 107349cc55cSDimitry Andric return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); 108349cc55cSDimitry Andric } 109*cb14a3feSDimitry Andric 110349cc55cSDimitry Andric private: 111349cc55cSDimitry Andric _ValueT __value_; 112349cc55cSDimitry Andric }; 113349cc55cSDimitry Andric 114349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less); 115349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv); 116349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); 117349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); 118349cc55cSDimitry Andric 119349cc55cSDimitry Andric class weak_ordering { 120349cc55cSDimitry Andric using _ValueT = signed char; 121349cc55cSDimitry Andric weak_ordering(_OrdResult __v)122*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 123349cc55cSDimitry Andric 124349cc55cSDimitry Andric public: 125349cc55cSDimitry Andric static const weak_ordering less; 126349cc55cSDimitry Andric static const weak_ordering equivalent; 127349cc55cSDimitry Andric static const weak_ordering greater; 128349cc55cSDimitry Andric partial_ordering()129*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept { 130349cc55cSDimitry Andric return __value_ == 0 ? partial_ordering::equivalent 131349cc55cSDimitry Andric : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 132349cc55cSDimitry Andric } 133349cc55cSDimitry Andric 134349cc55cSDimitry Andric // comparisons 135*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; 136349cc55cSDimitry Andric 137*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 138349cc55cSDimitry Andric return __v.__value_ == 0; 139349cc55cSDimitry Andric } 140349cc55cSDimitry Andric 141*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 142349cc55cSDimitry Andric return __v.__value_ < 0; 143349cc55cSDimitry Andric } 144349cc55cSDimitry Andric 145*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 146349cc55cSDimitry Andric return __v.__value_ <= 0; 147349cc55cSDimitry Andric } 148349cc55cSDimitry Andric 149*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 150349cc55cSDimitry Andric return __v.__value_ > 0; 151349cc55cSDimitry Andric } 152349cc55cSDimitry Andric 153*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 154349cc55cSDimitry Andric return __v.__value_ >= 0; 155349cc55cSDimitry Andric } 156349cc55cSDimitry Andric 157*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 158349cc55cSDimitry Andric return 0 < __v.__value_; 159349cc55cSDimitry Andric } 160349cc55cSDimitry Andric 161*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 162349cc55cSDimitry Andric return 0 <= __v.__value_; 163349cc55cSDimitry Andric } 164349cc55cSDimitry Andric 165*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 166349cc55cSDimitry Andric return 0 > __v.__value_; 167349cc55cSDimitry Andric } 168349cc55cSDimitry Andric 169*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 170349cc55cSDimitry Andric return 0 >= __v.__value_; 171349cc55cSDimitry Andric } 172349cc55cSDimitry Andric 173*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 174349cc55cSDimitry Andric return __v; 175349cc55cSDimitry Andric } 176349cc55cSDimitry Andric 177*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 178349cc55cSDimitry Andric return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); 179349cc55cSDimitry Andric } 180349cc55cSDimitry Andric 181349cc55cSDimitry Andric private: 182349cc55cSDimitry Andric _ValueT __value_; 183349cc55cSDimitry Andric }; 184349cc55cSDimitry Andric 185349cc55cSDimitry Andric inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less); 186349cc55cSDimitry Andric inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); 187349cc55cSDimitry Andric inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); 188349cc55cSDimitry Andric 189349cc55cSDimitry Andric class strong_ordering { 190349cc55cSDimitry Andric using _ValueT = signed char; 191349cc55cSDimitry Andric strong_ordering(_OrdResult __v)192*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 193349cc55cSDimitry Andric 194349cc55cSDimitry Andric public: 195349cc55cSDimitry Andric static const strong_ordering less; 196349cc55cSDimitry Andric static const strong_ordering equal; 197349cc55cSDimitry Andric static const strong_ordering equivalent; 198349cc55cSDimitry Andric static const strong_ordering greater; 199349cc55cSDimitry Andric 200349cc55cSDimitry Andric // conversions partial_ordering()201*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr operator partial_ordering() const noexcept { 202349cc55cSDimitry Andric return __value_ == 0 ? partial_ordering::equivalent 203349cc55cSDimitry Andric : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 204349cc55cSDimitry Andric } 205349cc55cSDimitry Andric weak_ordering()206*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr operator weak_ordering() const noexcept { 207*cb14a3feSDimitry Andric return __value_ == 0 ? weak_ordering::equivalent : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); 208349cc55cSDimitry Andric } 209349cc55cSDimitry Andric 210349cc55cSDimitry Andric // comparisons 211*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; 212349cc55cSDimitry Andric 213*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 214349cc55cSDimitry Andric return __v.__value_ == 0; 215349cc55cSDimitry Andric } 216349cc55cSDimitry Andric 217*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 218349cc55cSDimitry Andric return __v.__value_ < 0; 219349cc55cSDimitry Andric } 220349cc55cSDimitry Andric 221*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 222349cc55cSDimitry Andric return __v.__value_ <= 0; 223349cc55cSDimitry Andric } 224349cc55cSDimitry Andric 225*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 226349cc55cSDimitry Andric return __v.__value_ > 0; 227349cc55cSDimitry Andric } 228349cc55cSDimitry Andric 229*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 230349cc55cSDimitry Andric return __v.__value_ >= 0; 231349cc55cSDimitry Andric } 232349cc55cSDimitry Andric 233*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 234349cc55cSDimitry Andric return 0 < __v.__value_; 235349cc55cSDimitry Andric } 236349cc55cSDimitry Andric 237*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 238349cc55cSDimitry Andric return 0 <= __v.__value_; 239349cc55cSDimitry Andric } 240349cc55cSDimitry Andric 241*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 242349cc55cSDimitry Andric return 0 > __v.__value_; 243349cc55cSDimitry Andric } 244349cc55cSDimitry Andric 245*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 246349cc55cSDimitry Andric return 0 >= __v.__value_; 247349cc55cSDimitry Andric } 248349cc55cSDimitry Andric 249*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering 250*cb14a3feSDimitry Andric operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 251349cc55cSDimitry Andric return __v; 252349cc55cSDimitry Andric } 253349cc55cSDimitry Andric 254*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering 255*cb14a3feSDimitry Andric operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 256349cc55cSDimitry Andric return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); 257349cc55cSDimitry Andric } 258349cc55cSDimitry Andric 259349cc55cSDimitry Andric private: 260349cc55cSDimitry Andric _ValueT __value_; 261349cc55cSDimitry Andric }; 262349cc55cSDimitry Andric 263349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less); 264349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv); 265349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv); 266349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); 267349cc55cSDimitry Andric 268bdd1243dSDimitry Andric /// [cmp.categories.pre]/1 269bdd1243dSDimitry Andric /// The types partial_ordering, weak_ordering, and strong_ordering are 270bdd1243dSDimitry Andric /// collectively termed the comparison category types. 271bdd1243dSDimitry Andric template <class _Tp> 272bdd1243dSDimitry Andric concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>; 273bdd1243dSDimitry Andric 27406c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 275349cc55cSDimitry Andric 276349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD 277349cc55cSDimitry Andric 278349cc55cSDimitry Andric #endif // _LIBCPP___COMPARE_ORDERING_H 279