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> 13*bdd1243dSDimitry Andric #include <__type_traits/enable_if.h> 14*bdd1243dSDimitry 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 22349cc55cSDimitry Andric #if _LIBCPP_STD_VER > 17 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric // exposition only 25349cc55cSDimitry Andric enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { 26349cc55cSDimitry Andric __less = -1, 27349cc55cSDimitry Andric __equiv = 0, 28349cc55cSDimitry Andric __greater = 1 29349cc55cSDimitry Andric }; 30349cc55cSDimitry Andric 31349cc55cSDimitry Andric enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { 32349cc55cSDimitry Andric __unordered = -127 33349cc55cSDimitry Andric }; 34349cc55cSDimitry Andric 35349cc55cSDimitry Andric class partial_ordering; 36349cc55cSDimitry Andric class weak_ordering; 37349cc55cSDimitry Andric class strong_ordering; 38349cc55cSDimitry Andric 39349cc55cSDimitry Andric template<class _Tp, class... _Args> 40349cc55cSDimitry Andric inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); 41349cc55cSDimitry Andric 42349cc55cSDimitry Andric struct _CmpUnspecifiedParam { 43349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL 44349cc55cSDimitry Andric _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} 45349cc55cSDimitry Andric 46349cc55cSDimitry Andric template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>> 47349cc55cSDimitry Andric _CmpUnspecifiedParam(_Tp) = delete; 48349cc55cSDimitry Andric }; 49349cc55cSDimitry Andric 50349cc55cSDimitry Andric class partial_ordering { 51349cc55cSDimitry Andric using _ValueT = signed char; 52349cc55cSDimitry Andric 53349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 54349cc55cSDimitry Andric explicit constexpr partial_ordering(_OrdResult __v) noexcept 55349cc55cSDimitry Andric : __value_(_ValueT(__v)) {} 56349cc55cSDimitry Andric 57349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 58349cc55cSDimitry Andric explicit constexpr partial_ordering(_NCmpResult __v) noexcept 59349cc55cSDimitry Andric : __value_(_ValueT(__v)) {} 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 62349cc55cSDimitry Andric constexpr bool __is_ordered() const noexcept { 63349cc55cSDimitry Andric return __value_ != _ValueT(_NCmpResult::__unordered); 64349cc55cSDimitry Andric } 65349cc55cSDimitry Andric public: 66349cc55cSDimitry Andric // valid values 67349cc55cSDimitry Andric static const partial_ordering less; 68349cc55cSDimitry Andric static const partial_ordering equivalent; 69349cc55cSDimitry Andric static const partial_ordering greater; 70349cc55cSDimitry Andric static const partial_ordering unordered; 71349cc55cSDimitry Andric 72349cc55cSDimitry Andric // comparisons 73349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 74349cc55cSDimitry Andric friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; 75349cc55cSDimitry Andric 76349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 77349cc55cSDimitry Andric friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 78349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ == 0; 79349cc55cSDimitry Andric } 80349cc55cSDimitry Andric 81349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 82349cc55cSDimitry Andric friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 83349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ < 0; 84349cc55cSDimitry Andric } 85349cc55cSDimitry Andric 86349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 87349cc55cSDimitry Andric friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 88349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ <= 0; 89349cc55cSDimitry Andric } 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 92349cc55cSDimitry Andric friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 93349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ > 0; 94349cc55cSDimitry Andric } 95349cc55cSDimitry Andric 96349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 97349cc55cSDimitry Andric friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 98349cc55cSDimitry Andric return __v.__is_ordered() && __v.__value_ >= 0; 99349cc55cSDimitry Andric } 100349cc55cSDimitry Andric 101349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 102349cc55cSDimitry Andric friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 103349cc55cSDimitry Andric return __v.__is_ordered() && 0 < __v.__value_; 104349cc55cSDimitry Andric } 105349cc55cSDimitry Andric 106349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 107349cc55cSDimitry Andric friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 108349cc55cSDimitry Andric return __v.__is_ordered() && 0 <= __v.__value_; 109349cc55cSDimitry Andric } 110349cc55cSDimitry Andric 111349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 112349cc55cSDimitry Andric friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 113349cc55cSDimitry Andric return __v.__is_ordered() && 0 > __v.__value_; 114349cc55cSDimitry Andric } 115349cc55cSDimitry Andric 116349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 117349cc55cSDimitry Andric friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 118349cc55cSDimitry Andric return __v.__is_ordered() && 0 >= __v.__value_; 119349cc55cSDimitry Andric } 120349cc55cSDimitry Andric 121349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 122349cc55cSDimitry Andric friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 123349cc55cSDimitry Andric return __v; 124349cc55cSDimitry Andric } 125349cc55cSDimitry Andric 126349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 127349cc55cSDimitry Andric friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 128349cc55cSDimitry Andric return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); 129349cc55cSDimitry Andric } 130349cc55cSDimitry Andric private: 131349cc55cSDimitry Andric _ValueT __value_; 132349cc55cSDimitry Andric }; 133349cc55cSDimitry Andric 134349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less); 135349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv); 136349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); 137349cc55cSDimitry Andric inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); 138349cc55cSDimitry Andric 139349cc55cSDimitry Andric class weak_ordering { 140349cc55cSDimitry Andric using _ValueT = signed char; 141349cc55cSDimitry Andric 142349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 143349cc55cSDimitry Andric explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 144349cc55cSDimitry Andric 145349cc55cSDimitry Andric public: 146349cc55cSDimitry Andric static const weak_ordering less; 147349cc55cSDimitry Andric static const weak_ordering equivalent; 148349cc55cSDimitry Andric static const weak_ordering greater; 149349cc55cSDimitry Andric 150349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 151349cc55cSDimitry Andric constexpr operator partial_ordering() const noexcept { 152349cc55cSDimitry Andric return __value_ == 0 ? partial_ordering::equivalent 153349cc55cSDimitry Andric : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 154349cc55cSDimitry Andric } 155349cc55cSDimitry Andric 156349cc55cSDimitry Andric // comparisons 157349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 158349cc55cSDimitry Andric friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; 159349cc55cSDimitry Andric 160349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 161349cc55cSDimitry Andric friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 162349cc55cSDimitry Andric return __v.__value_ == 0; 163349cc55cSDimitry Andric } 164349cc55cSDimitry Andric 165349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 166349cc55cSDimitry Andric friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 167349cc55cSDimitry Andric return __v.__value_ < 0; 168349cc55cSDimitry Andric } 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 171349cc55cSDimitry Andric friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 172349cc55cSDimitry Andric return __v.__value_ <= 0; 173349cc55cSDimitry Andric } 174349cc55cSDimitry Andric 175349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 176349cc55cSDimitry Andric friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 177349cc55cSDimitry Andric return __v.__value_ > 0; 178349cc55cSDimitry Andric } 179349cc55cSDimitry Andric 180349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 181349cc55cSDimitry Andric friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 182349cc55cSDimitry Andric return __v.__value_ >= 0; 183349cc55cSDimitry Andric } 184349cc55cSDimitry Andric 185349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 186349cc55cSDimitry Andric friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 187349cc55cSDimitry Andric return 0 < __v.__value_; 188349cc55cSDimitry Andric } 189349cc55cSDimitry Andric 190349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 191349cc55cSDimitry Andric friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 192349cc55cSDimitry Andric return 0 <= __v.__value_; 193349cc55cSDimitry Andric } 194349cc55cSDimitry Andric 195349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 196349cc55cSDimitry Andric friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 197349cc55cSDimitry Andric return 0 > __v.__value_; 198349cc55cSDimitry Andric } 199349cc55cSDimitry Andric 200349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 201349cc55cSDimitry Andric friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 202349cc55cSDimitry Andric return 0 >= __v.__value_; 203349cc55cSDimitry Andric } 204349cc55cSDimitry Andric 205349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 206349cc55cSDimitry Andric friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 207349cc55cSDimitry Andric return __v; 208349cc55cSDimitry Andric } 209349cc55cSDimitry Andric 210349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 211349cc55cSDimitry Andric friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 212349cc55cSDimitry Andric return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); 213349cc55cSDimitry Andric } 214349cc55cSDimitry Andric 215349cc55cSDimitry Andric private: 216349cc55cSDimitry Andric _ValueT __value_; 217349cc55cSDimitry Andric }; 218349cc55cSDimitry Andric 219349cc55cSDimitry Andric inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less); 220349cc55cSDimitry Andric inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); 221349cc55cSDimitry Andric inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); 222349cc55cSDimitry Andric 223349cc55cSDimitry Andric class strong_ordering { 224349cc55cSDimitry Andric using _ValueT = signed char; 225349cc55cSDimitry Andric 226349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 227349cc55cSDimitry Andric explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 228349cc55cSDimitry Andric 229349cc55cSDimitry Andric public: 230349cc55cSDimitry Andric static const strong_ordering less; 231349cc55cSDimitry Andric static const strong_ordering equal; 232349cc55cSDimitry Andric static const strong_ordering equivalent; 233349cc55cSDimitry Andric static const strong_ordering greater; 234349cc55cSDimitry Andric 235349cc55cSDimitry Andric // conversions 236349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 237349cc55cSDimitry Andric constexpr operator partial_ordering() const noexcept { 238349cc55cSDimitry Andric return __value_ == 0 ? partial_ordering::equivalent 239349cc55cSDimitry Andric : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 240349cc55cSDimitry Andric } 241349cc55cSDimitry Andric 242349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 243349cc55cSDimitry Andric constexpr operator weak_ordering() const noexcept { 244349cc55cSDimitry Andric return __value_ == 0 ? weak_ordering::equivalent 245349cc55cSDimitry Andric : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); 246349cc55cSDimitry Andric } 247349cc55cSDimitry Andric 248349cc55cSDimitry Andric // comparisons 249349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 250349cc55cSDimitry Andric friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; 251349cc55cSDimitry Andric 252349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 253349cc55cSDimitry Andric friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 254349cc55cSDimitry Andric return __v.__value_ == 0; 255349cc55cSDimitry Andric } 256349cc55cSDimitry Andric 257349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 258349cc55cSDimitry Andric friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 259349cc55cSDimitry Andric return __v.__value_ < 0; 260349cc55cSDimitry Andric } 261349cc55cSDimitry Andric 262349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 263349cc55cSDimitry Andric friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 264349cc55cSDimitry Andric return __v.__value_ <= 0; 265349cc55cSDimitry Andric } 266349cc55cSDimitry Andric 267349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 268349cc55cSDimitry Andric friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 269349cc55cSDimitry Andric return __v.__value_ > 0; 270349cc55cSDimitry Andric } 271349cc55cSDimitry Andric 272349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 273349cc55cSDimitry Andric friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 274349cc55cSDimitry Andric return __v.__value_ >= 0; 275349cc55cSDimitry Andric } 276349cc55cSDimitry Andric 277349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 278349cc55cSDimitry Andric friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 279349cc55cSDimitry Andric return 0 < __v.__value_; 280349cc55cSDimitry Andric } 281349cc55cSDimitry Andric 282349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 283349cc55cSDimitry Andric friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 284349cc55cSDimitry Andric return 0 <= __v.__value_; 285349cc55cSDimitry Andric } 286349cc55cSDimitry Andric 287349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 288349cc55cSDimitry Andric friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 289349cc55cSDimitry Andric return 0 > __v.__value_; 290349cc55cSDimitry Andric } 291349cc55cSDimitry Andric 292349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 293349cc55cSDimitry Andric friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 294349cc55cSDimitry Andric return 0 >= __v.__value_; 295349cc55cSDimitry Andric } 296349cc55cSDimitry Andric 297349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 298349cc55cSDimitry Andric friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 299349cc55cSDimitry Andric return __v; 300349cc55cSDimitry Andric } 301349cc55cSDimitry Andric 302349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI 303349cc55cSDimitry Andric friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 304349cc55cSDimitry Andric return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); 305349cc55cSDimitry Andric } 306349cc55cSDimitry Andric 307349cc55cSDimitry Andric private: 308349cc55cSDimitry Andric _ValueT __value_; 309349cc55cSDimitry Andric }; 310349cc55cSDimitry Andric 311349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less); 312349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv); 313349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv); 314349cc55cSDimitry Andric inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); 315349cc55cSDimitry Andric 316*bdd1243dSDimitry Andric /// [cmp.categories.pre]/1 317*bdd1243dSDimitry Andric /// The types partial_ordering, weak_ordering, and strong_ordering are 318*bdd1243dSDimitry Andric /// collectively termed the comparison category types. 319*bdd1243dSDimitry Andric template <class _Tp> 320*bdd1243dSDimitry Andric concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>; 321*bdd1243dSDimitry Andric 322349cc55cSDimitry Andric #endif // _LIBCPP_STD_VER > 17 323349cc55cSDimitry Andric 324349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD 325349cc55cSDimitry Andric 326349cc55cSDimitry Andric #endif // _LIBCPP___COMPARE_ORDERING_H 327