1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // compare.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This header file defines the `absl::weak_equality`, `absl::strong_equality`, 20 // `absl::partial_ordering`, `absl::weak_ordering`, and `absl::strong_ordering` 21 // types for storing the results of three way comparisons. 22 // 23 // Example: 24 // absl::weak_ordering compare(const std::string& a, const std::string& b); 25 // 26 // These are C++11 compatible versions of the C++20 corresponding types 27 // (`std::weak_equality`, etc.) and are designed to be drop-in replacements 28 // for code compliant with C++20. 29 30 #ifndef ABSL_TYPES_COMPARE_H_ 31 #define ABSL_TYPES_COMPARE_H_ 32 33 #include <cstddef> 34 #include <cstdint> 35 #include <cstdlib> 36 #include <type_traits> 37 38 #include "absl/base/attributes.h" 39 #include "absl/meta/type_traits.h" 40 41 namespace absl { 42 ABSL_NAMESPACE_BEGIN 43 namespace compare_internal { 44 45 using value_type = int8_t; 46 47 template <typename T> 48 struct Fail { 49 static_assert(sizeof(T) < 0, "Only literal `0` is allowed."); 50 }; 51 52 // We need the NullPtrT template to avoid triggering the modernize-use-nullptr 53 // ClangTidy warning in user code. 54 template <typename NullPtrT = std::nullptr_t> 55 struct OnlyLiteralZero { OnlyLiteralZeroOnlyLiteralZero56 constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT 57 58 // Fails compilation when `nullptr` or integral type arguments other than 59 // `int` are passed. This constructor doesn't accept `int` because literal `0` 60 // has type `int`. Literal `0` arguments will be implicitly converted to 61 // `std::nullptr_t` and accepted by the above constructor, while other `int` 62 // arguments will fail to be converted and cause compilation failure. 63 template < 64 typename T, 65 typename = typename std::enable_if< 66 std::is_same<T, std::nullptr_t>::value || 67 (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type, 68 typename = typename Fail<T>::type> 69 OnlyLiteralZero(T); // NOLINT 70 }; 71 72 enum class eq : value_type { 73 equal = 0, 74 equivalent = equal, 75 nonequal = 1, 76 nonequivalent = nonequal, 77 }; 78 79 enum class ord : value_type { less = -1, greater = 1 }; 80 81 enum class ncmp : value_type { unordered = -127 }; 82 83 // Define macros to allow for creation or emulation of C++17 inline variables 84 // based on whether the feature is supported. Note: we can't use 85 // ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of 86 // incomplete types so they need to be defined after the types are complete. 87 #ifdef __cpp_inline_variables 88 89 // A no-op expansion that can be followed by a semicolon at class level. 90 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "") 91 92 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \ 93 static const type name 94 95 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \ 96 inline constexpr type type::name(init) 97 98 #else // __cpp_inline_variables 99 100 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \ 101 ABSL_CONST_INIT static const T name 102 103 // A no-op expansion that can be followed by a semicolon at class level. 104 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "") 105 106 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \ 107 template <typename T> \ 108 const T compare_internal::type##_base<T>::name(init) 109 110 #endif // __cpp_inline_variables 111 112 // These template base classes allow for defining the values of the constants 113 // in the header file (for performance) without using inline variables (which 114 // aren't available in C++11). 115 template <typename T> 116 struct weak_equality_base { 117 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 118 ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); 119 }; 120 121 template <typename T> 122 struct strong_equality_base { 123 ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); 124 ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequal); 125 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 126 ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); 127 }; 128 129 template <typename T> 130 struct partial_ordering_base { 131 ABSL_COMPARE_INLINE_BASECLASS_DECL(less); 132 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 133 ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); 134 ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered); 135 }; 136 137 template <typename T> 138 struct weak_ordering_base { 139 ABSL_COMPARE_INLINE_BASECLASS_DECL(less); 140 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 141 ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); 142 }; 143 144 template <typename T> 145 struct strong_ordering_base { 146 ABSL_COMPARE_INLINE_BASECLASS_DECL(less); 147 ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); 148 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 149 ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); 150 }; 151 152 } // namespace compare_internal 153 154 class weak_equality 155 : public compare_internal::weak_equality_base<weak_equality> { weak_equality(compare_internal::eq v)156 explicit constexpr weak_equality(compare_internal::eq v) noexcept 157 : value_(static_cast<compare_internal::value_type>(v)) {} 158 friend struct compare_internal::weak_equality_base<weak_equality>; 159 160 public: 161 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent); 162 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent); 163 164 // Comparisons 165 friend constexpr bool operator==( 166 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 167 return v.value_ == 0; 168 } 169 friend constexpr bool operator!=( 170 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 171 return v.value_ != 0; 172 } 173 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 174 weak_equality v) noexcept { 175 return 0 == v.value_; 176 } 177 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 178 weak_equality v) noexcept { 179 return 0 != v.value_; 180 } 181 friend constexpr bool operator==(weak_equality v1, 182 weak_equality v2) noexcept { 183 return v1.value_ == v2.value_; 184 } 185 friend constexpr bool operator!=(weak_equality v1, 186 weak_equality v2) noexcept { 187 return v1.value_ != v2.value_; 188 } 189 190 private: 191 compare_internal::value_type value_; 192 }; 193 ABSL_COMPARE_INLINE_INIT(weak_equality, equivalent, 194 compare_internal::eq::equivalent); 195 ABSL_COMPARE_INLINE_INIT(weak_equality, nonequivalent, 196 compare_internal::eq::nonequivalent); 197 198 class strong_equality 199 : public compare_internal::strong_equality_base<strong_equality> { 200 explicit constexpr strong_equality(compare_internal::eq v) noexcept 201 : value_(static_cast<compare_internal::value_type>(v)) {} 202 friend struct compare_internal::strong_equality_base<strong_equality>; 203 204 public: 205 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal); 206 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal); 207 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent); 208 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent); 209 210 // Conversion 211 constexpr operator weak_equality() const noexcept { // NOLINT 212 return value_ == 0 ? weak_equality::equivalent 213 : weak_equality::nonequivalent; 214 } 215 // Comparisons 216 friend constexpr bool operator==( 217 strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 218 return v.value_ == 0; 219 } 220 friend constexpr bool operator!=( 221 strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 222 return v.value_ != 0; 223 } 224 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 225 strong_equality v) noexcept { 226 return 0 == v.value_; 227 } 228 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 229 strong_equality v) noexcept { 230 return 0 != v.value_; 231 } 232 friend constexpr bool operator==(strong_equality v1, 233 strong_equality v2) noexcept { 234 return v1.value_ == v2.value_; 235 } 236 friend constexpr bool operator!=(strong_equality v1, 237 strong_equality v2) noexcept { 238 return v1.value_ != v2.value_; 239 } 240 241 private: 242 compare_internal::value_type value_; 243 }; 244 ABSL_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal); 245 ABSL_COMPARE_INLINE_INIT(strong_equality, nonequal, 246 compare_internal::eq::nonequal); 247 ABSL_COMPARE_INLINE_INIT(strong_equality, equivalent, 248 compare_internal::eq::equivalent); 249 ABSL_COMPARE_INLINE_INIT(strong_equality, nonequivalent, 250 compare_internal::eq::nonequivalent); 251 252 class partial_ordering 253 : public compare_internal::partial_ordering_base<partial_ordering> { 254 explicit constexpr partial_ordering(compare_internal::eq v) noexcept 255 : value_(static_cast<compare_internal::value_type>(v)) {} 256 explicit constexpr partial_ordering(compare_internal::ord v) noexcept 257 : value_(static_cast<compare_internal::value_type>(v)) {} 258 explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept 259 : value_(static_cast<compare_internal::value_type>(v)) {} 260 friend struct compare_internal::partial_ordering_base<partial_ordering>; 261 262 constexpr bool is_ordered() const noexcept { 263 return value_ != 264 compare_internal::value_type(compare_internal::ncmp::unordered); 265 } 266 267 public: 268 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less); 269 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent); 270 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater); 271 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered); 272 273 // Conversion 274 constexpr operator weak_equality() const noexcept { // NOLINT 275 return value_ == 0 ? weak_equality::equivalent 276 : weak_equality::nonequivalent; 277 } 278 // Comparisons 279 friend constexpr bool operator==( 280 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 281 return v.is_ordered() && v.value_ == 0; 282 } 283 friend constexpr bool operator!=( 284 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 285 return !v.is_ordered() || v.value_ != 0; 286 } 287 friend constexpr bool operator<( 288 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 289 return v.is_ordered() && v.value_ < 0; 290 } 291 friend constexpr bool operator<=( 292 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 293 return v.is_ordered() && v.value_ <= 0; 294 } 295 friend constexpr bool operator>( 296 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 297 return v.is_ordered() && v.value_ > 0; 298 } 299 friend constexpr bool operator>=( 300 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 301 return v.is_ordered() && v.value_ >= 0; 302 } 303 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 304 partial_ordering v) noexcept { 305 return v.is_ordered() && 0 == v.value_; 306 } 307 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 308 partial_ordering v) noexcept { 309 return !v.is_ordered() || 0 != v.value_; 310 } 311 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, 312 partial_ordering v) noexcept { 313 return v.is_ordered() && 0 < v.value_; 314 } 315 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, 316 partial_ordering v) noexcept { 317 return v.is_ordered() && 0 <= v.value_; 318 } 319 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, 320 partial_ordering v) noexcept { 321 return v.is_ordered() && 0 > v.value_; 322 } 323 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, 324 partial_ordering v) noexcept { 325 return v.is_ordered() && 0 >= v.value_; 326 } 327 friend constexpr bool operator==(partial_ordering v1, 328 partial_ordering v2) noexcept { 329 return v1.value_ == v2.value_; 330 } 331 friend constexpr bool operator!=(partial_ordering v1, 332 partial_ordering v2) noexcept { 333 return v1.value_ != v2.value_; 334 } 335 336 private: 337 compare_internal::value_type value_; 338 }; 339 ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less); 340 ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent, 341 compare_internal::eq::equivalent); 342 ABSL_COMPARE_INLINE_INIT(partial_ordering, greater, 343 compare_internal::ord::greater); 344 ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered, 345 compare_internal::ncmp::unordered); 346 347 class weak_ordering 348 : public compare_internal::weak_ordering_base<weak_ordering> { 349 explicit constexpr weak_ordering(compare_internal::eq v) noexcept 350 : value_(static_cast<compare_internal::value_type>(v)) {} 351 explicit constexpr weak_ordering(compare_internal::ord v) noexcept 352 : value_(static_cast<compare_internal::value_type>(v)) {} 353 friend struct compare_internal::weak_ordering_base<weak_ordering>; 354 355 public: 356 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less); 357 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent); 358 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater); 359 360 // Conversions 361 constexpr operator weak_equality() const noexcept { // NOLINT 362 return value_ == 0 ? weak_equality::equivalent 363 : weak_equality::nonequivalent; 364 } 365 constexpr operator partial_ordering() const noexcept { // NOLINT 366 return value_ == 0 ? partial_ordering::equivalent 367 : (value_ < 0 ? partial_ordering::less 368 : partial_ordering::greater); 369 } 370 // Comparisons 371 friend constexpr bool operator==( 372 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 373 return v.value_ == 0; 374 } 375 friend constexpr bool operator!=( 376 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 377 return v.value_ != 0; 378 } 379 friend constexpr bool operator<( 380 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 381 return v.value_ < 0; 382 } 383 friend constexpr bool operator<=( 384 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 385 return v.value_ <= 0; 386 } 387 friend constexpr bool operator>( 388 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 389 return v.value_ > 0; 390 } 391 friend constexpr bool operator>=( 392 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 393 return v.value_ >= 0; 394 } 395 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 396 weak_ordering v) noexcept { 397 return 0 == v.value_; 398 } 399 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 400 weak_ordering v) noexcept { 401 return 0 != v.value_; 402 } 403 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, 404 weak_ordering v) noexcept { 405 return 0 < v.value_; 406 } 407 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, 408 weak_ordering v) noexcept { 409 return 0 <= v.value_; 410 } 411 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, 412 weak_ordering v) noexcept { 413 return 0 > v.value_; 414 } 415 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, 416 weak_ordering v) noexcept { 417 return 0 >= v.value_; 418 } 419 friend constexpr bool operator==(weak_ordering v1, 420 weak_ordering v2) noexcept { 421 return v1.value_ == v2.value_; 422 } 423 friend constexpr bool operator!=(weak_ordering v1, 424 weak_ordering v2) noexcept { 425 return v1.value_ != v2.value_; 426 } 427 428 private: 429 compare_internal::value_type value_; 430 }; 431 ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less); 432 ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent, 433 compare_internal::eq::equivalent); 434 ABSL_COMPARE_INLINE_INIT(weak_ordering, greater, 435 compare_internal::ord::greater); 436 437 class strong_ordering 438 : public compare_internal::strong_ordering_base<strong_ordering> { 439 explicit constexpr strong_ordering(compare_internal::eq v) noexcept 440 : value_(static_cast<compare_internal::value_type>(v)) {} 441 explicit constexpr strong_ordering(compare_internal::ord v) noexcept 442 : value_(static_cast<compare_internal::value_type>(v)) {} 443 friend struct compare_internal::strong_ordering_base<strong_ordering>; 444 445 public: 446 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less); 447 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal); 448 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent); 449 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater); 450 451 // Conversions 452 constexpr operator weak_equality() const noexcept { // NOLINT 453 return value_ == 0 ? weak_equality::equivalent 454 : weak_equality::nonequivalent; 455 } 456 constexpr operator strong_equality() const noexcept { // NOLINT 457 return value_ == 0 ? strong_equality::equal : strong_equality::nonequal; 458 } 459 constexpr operator partial_ordering() const noexcept { // NOLINT 460 return value_ == 0 ? partial_ordering::equivalent 461 : (value_ < 0 ? partial_ordering::less 462 : partial_ordering::greater); 463 } 464 constexpr operator weak_ordering() const noexcept { // NOLINT 465 return value_ == 0 466 ? weak_ordering::equivalent 467 : (value_ < 0 ? weak_ordering::less : weak_ordering::greater); 468 } 469 // Comparisons 470 friend constexpr bool operator==( 471 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 472 return v.value_ == 0; 473 } 474 friend constexpr bool operator!=( 475 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 476 return v.value_ != 0; 477 } 478 friend constexpr bool operator<( 479 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 480 return v.value_ < 0; 481 } 482 friend constexpr bool operator<=( 483 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 484 return v.value_ <= 0; 485 } 486 friend constexpr bool operator>( 487 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 488 return v.value_ > 0; 489 } 490 friend constexpr bool operator>=( 491 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 492 return v.value_ >= 0; 493 } 494 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 495 strong_ordering v) noexcept { 496 return 0 == v.value_; 497 } 498 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 499 strong_ordering v) noexcept { 500 return 0 != v.value_; 501 } 502 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, 503 strong_ordering v) noexcept { 504 return 0 < v.value_; 505 } 506 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, 507 strong_ordering v) noexcept { 508 return 0 <= v.value_; 509 } 510 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, 511 strong_ordering v) noexcept { 512 return 0 > v.value_; 513 } 514 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, 515 strong_ordering v) noexcept { 516 return 0 >= v.value_; 517 } 518 friend constexpr bool operator==(strong_ordering v1, 519 strong_ordering v2) noexcept { 520 return v1.value_ == v2.value_; 521 } 522 friend constexpr bool operator!=(strong_ordering v1, 523 strong_ordering v2) noexcept { 524 return v1.value_ != v2.value_; 525 } 526 527 private: 528 compare_internal::value_type value_; 529 }; 530 ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less); 531 ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal); 532 ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent, 533 compare_internal::eq::equivalent); 534 ABSL_COMPARE_INLINE_INIT(strong_ordering, greater, 535 compare_internal::ord::greater); 536 537 #undef ABSL_COMPARE_INLINE_BASECLASS_DECL 538 #undef ABSL_COMPARE_INLINE_SUBCLASS_DECL 539 #undef ABSL_COMPARE_INLINE_INIT 540 541 namespace compare_internal { 542 // We also provide these comparator adapter functions for internal absl use. 543 544 // Helper functions to do a boolean comparison of two keys given a boolean 545 // or three-way comparator. 546 // SFINAE prevents implicit conversions to bool (such as from int). 547 template <typename Bool, 548 absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0> 549 constexpr bool compare_result_as_less_than(const Bool r) { return r; } 550 constexpr bool compare_result_as_less_than(const absl::weak_ordering r) { 551 return r < 0; 552 } 553 554 template <typename Compare, typename K, typename LK> 555 constexpr bool do_less_than_comparison(const Compare &compare, const K &x, 556 const LK &y) { 557 return compare_result_as_less_than(compare(x, y)); 558 } 559 560 // Helper functions to do a three-way comparison of two keys given a boolean or 561 // three-way comparator. 562 // SFINAE prevents implicit conversions to int (such as from bool). 563 template <typename Int, 564 absl::enable_if_t<std::is_same<int, Int>::value, int> = 0> 565 constexpr absl::weak_ordering compare_result_as_ordering(const Int c) { 566 return c < 0 ? absl::weak_ordering::less 567 : c == 0 ? absl::weak_ordering::equivalent 568 : absl::weak_ordering::greater; 569 } 570 constexpr absl::weak_ordering compare_result_as_ordering( 571 const absl::weak_ordering c) { 572 return c; 573 } 574 575 template < 576 typename Compare, typename K, typename LK, 577 absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare( 578 const K &, const LK &)>>::value, 579 int> = 0> 580 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, 581 const K &x, const LK &y) { 582 return compare_result_as_ordering(compare(x, y)); 583 } 584 template < 585 typename Compare, typename K, typename LK, 586 absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare( 587 const K &, const LK &)>>::value, 588 int> = 0> 589 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, 590 const K &x, const LK &y) { 591 return compare(x, y) ? absl::weak_ordering::less 592 : compare(y, x) ? absl::weak_ordering::greater 593 : absl::weak_ordering::equivalent; 594 } 595 596 } // namespace compare_internal 597 ABSL_NAMESPACE_END 598 } // namespace absl 599 600 #endif // ABSL_TYPES_COMPARE_H_ 601