1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___COMPARE_ORDERING_H 10 #define _LIBCPP___COMPARE_ORDERING_H 11 12 #include <__config> 13 #include <__type_traits/enable_if.h> 14 #include <__type_traits/is_same.h> 15 16 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 17 # pragma GCC system_header 18 #endif 19 20 _LIBCPP_BEGIN_NAMESPACE_STD 21 22 #if _LIBCPP_STD_VER >= 20 23 24 // exposition only 25 enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { 26 __less = -1, 27 __equiv = 0, 28 __greater = 1 29 }; 30 31 enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { 32 __unordered = -127 33 }; 34 35 class partial_ordering; 36 class weak_ordering; 37 class strong_ordering; 38 39 template<class _Tp, class... _Args> 40 inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); 41 42 struct _CmpUnspecifiedParam { 43 _LIBCPP_HIDE_FROM_ABI constexpr 44 _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} 45 46 template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>> 47 _CmpUnspecifiedParam(_Tp) = delete; 48 }; 49 50 class partial_ordering { 51 using _ValueT = signed char; 52 53 _LIBCPP_HIDE_FROM_ABI 54 explicit constexpr partial_ordering(_OrdResult __v) noexcept 55 : __value_(_ValueT(__v)) {} 56 57 _LIBCPP_HIDE_FROM_ABI 58 explicit constexpr partial_ordering(_NCmpResult __v) noexcept 59 : __value_(_ValueT(__v)) {} 60 61 _LIBCPP_HIDE_FROM_ABI 62 constexpr bool __is_ordered() const noexcept { 63 return __value_ != _ValueT(_NCmpResult::__unordered); 64 } 65 public: 66 // valid values 67 static const partial_ordering less; 68 static const partial_ordering equivalent; 69 static const partial_ordering greater; 70 static const partial_ordering unordered; 71 72 // comparisons 73 _LIBCPP_HIDE_FROM_ABI 74 friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; 75 76 _LIBCPP_HIDE_FROM_ABI 77 friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 78 return __v.__is_ordered() && __v.__value_ == 0; 79 } 80 81 _LIBCPP_HIDE_FROM_ABI 82 friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 83 return __v.__is_ordered() && __v.__value_ < 0; 84 } 85 86 _LIBCPP_HIDE_FROM_ABI 87 friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 88 return __v.__is_ordered() && __v.__value_ <= 0; 89 } 90 91 _LIBCPP_HIDE_FROM_ABI 92 friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 93 return __v.__is_ordered() && __v.__value_ > 0; 94 } 95 96 _LIBCPP_HIDE_FROM_ABI 97 friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 98 return __v.__is_ordered() && __v.__value_ >= 0; 99 } 100 101 _LIBCPP_HIDE_FROM_ABI 102 friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 103 return __v.__is_ordered() && 0 < __v.__value_; 104 } 105 106 _LIBCPP_HIDE_FROM_ABI 107 friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 108 return __v.__is_ordered() && 0 <= __v.__value_; 109 } 110 111 _LIBCPP_HIDE_FROM_ABI 112 friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 113 return __v.__is_ordered() && 0 > __v.__value_; 114 } 115 116 _LIBCPP_HIDE_FROM_ABI 117 friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 118 return __v.__is_ordered() && 0 >= __v.__value_; 119 } 120 121 _LIBCPP_HIDE_FROM_ABI 122 friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 123 return __v; 124 } 125 126 _LIBCPP_HIDE_FROM_ABI 127 friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 128 return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); 129 } 130 private: 131 _ValueT __value_; 132 }; 133 134 inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less); 135 inline constexpr partial_ordering partial_ordering::equivalent(_OrdResult::__equiv); 136 inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); 137 inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); 138 139 class weak_ordering { 140 using _ValueT = signed char; 141 142 _LIBCPP_HIDE_FROM_ABI 143 explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 144 145 public: 146 static const weak_ordering less; 147 static const weak_ordering equivalent; 148 static const weak_ordering greater; 149 150 _LIBCPP_HIDE_FROM_ABI 151 constexpr operator partial_ordering() const noexcept { 152 return __value_ == 0 ? partial_ordering::equivalent 153 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 154 } 155 156 // comparisons 157 _LIBCPP_HIDE_FROM_ABI 158 friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; 159 160 _LIBCPP_HIDE_FROM_ABI 161 friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 162 return __v.__value_ == 0; 163 } 164 165 _LIBCPP_HIDE_FROM_ABI 166 friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 167 return __v.__value_ < 0; 168 } 169 170 _LIBCPP_HIDE_FROM_ABI 171 friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 172 return __v.__value_ <= 0; 173 } 174 175 _LIBCPP_HIDE_FROM_ABI 176 friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 177 return __v.__value_ > 0; 178 } 179 180 _LIBCPP_HIDE_FROM_ABI 181 friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 182 return __v.__value_ >= 0; 183 } 184 185 _LIBCPP_HIDE_FROM_ABI 186 friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 187 return 0 < __v.__value_; 188 } 189 190 _LIBCPP_HIDE_FROM_ABI 191 friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 192 return 0 <= __v.__value_; 193 } 194 195 _LIBCPP_HIDE_FROM_ABI 196 friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 197 return 0 > __v.__value_; 198 } 199 200 _LIBCPP_HIDE_FROM_ABI 201 friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 202 return 0 >= __v.__value_; 203 } 204 205 _LIBCPP_HIDE_FROM_ABI 206 friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 207 return __v; 208 } 209 210 _LIBCPP_HIDE_FROM_ABI 211 friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 212 return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); 213 } 214 215 private: 216 _ValueT __value_; 217 }; 218 219 inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less); 220 inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); 221 inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); 222 223 class strong_ordering { 224 using _ValueT = signed char; 225 226 _LIBCPP_HIDE_FROM_ABI 227 explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 228 229 public: 230 static const strong_ordering less; 231 static const strong_ordering equal; 232 static const strong_ordering equivalent; 233 static const strong_ordering greater; 234 235 // conversions 236 _LIBCPP_HIDE_FROM_ABI 237 constexpr operator partial_ordering() const noexcept { 238 return __value_ == 0 ? partial_ordering::equivalent 239 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 240 } 241 242 _LIBCPP_HIDE_FROM_ABI 243 constexpr operator weak_ordering() const noexcept { 244 return __value_ == 0 ? weak_ordering::equivalent 245 : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); 246 } 247 248 // comparisons 249 _LIBCPP_HIDE_FROM_ABI 250 friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; 251 252 _LIBCPP_HIDE_FROM_ABI 253 friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 254 return __v.__value_ == 0; 255 } 256 257 _LIBCPP_HIDE_FROM_ABI 258 friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 259 return __v.__value_ < 0; 260 } 261 262 _LIBCPP_HIDE_FROM_ABI 263 friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 264 return __v.__value_ <= 0; 265 } 266 267 _LIBCPP_HIDE_FROM_ABI 268 friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 269 return __v.__value_ > 0; 270 } 271 272 _LIBCPP_HIDE_FROM_ABI 273 friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 274 return __v.__value_ >= 0; 275 } 276 277 _LIBCPP_HIDE_FROM_ABI 278 friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 279 return 0 < __v.__value_; 280 } 281 282 _LIBCPP_HIDE_FROM_ABI 283 friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 284 return 0 <= __v.__value_; 285 } 286 287 _LIBCPP_HIDE_FROM_ABI 288 friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 289 return 0 > __v.__value_; 290 } 291 292 _LIBCPP_HIDE_FROM_ABI 293 friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 294 return 0 >= __v.__value_; 295 } 296 297 _LIBCPP_HIDE_FROM_ABI 298 friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 299 return __v; 300 } 301 302 _LIBCPP_HIDE_FROM_ABI 303 friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 304 return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); 305 } 306 307 private: 308 _ValueT __value_; 309 }; 310 311 inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less); 312 inline constexpr strong_ordering strong_ordering::equal(_OrdResult::__equiv); 313 inline constexpr strong_ordering strong_ordering::equivalent(_OrdResult::__equiv); 314 inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); 315 316 /// [cmp.categories.pre]/1 317 /// The types partial_ordering, weak_ordering, and strong_ordering are 318 /// collectively termed the comparison category types. 319 template <class _Tp> 320 concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>; 321 322 #endif // _LIBCPP_STD_VER >= 20 323 324 _LIBCPP_END_NAMESPACE_STD 325 326 #endif // _LIBCPP___COMPARE_ORDERING_H 327