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 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) 90 91 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \ 92 static const type name 93 94 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \ 95 inline constexpr type type::name(init) 96 97 #else // __cpp_inline_variables 98 99 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \ 100 ABSL_CONST_INIT static const T name 101 102 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) 103 104 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \ 105 template <typename T> \ 106 const T compare_internal::type##_base<T>::name(init) 107 108 #endif // __cpp_inline_variables 109 110 // These template base classes allow for defining the values of the constants 111 // in the header file (for performance) without using inline variables (which 112 // aren't available in C++11). 113 template <typename T> 114 struct weak_equality_base { 115 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 116 ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); 117 }; 118 119 template <typename T> 120 struct strong_equality_base { 121 ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); 122 ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequal); 123 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 124 ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); 125 }; 126 127 template <typename T> 128 struct partial_ordering_base { 129 ABSL_COMPARE_INLINE_BASECLASS_DECL(less); 130 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 131 ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); 132 ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered); 133 }; 134 135 template <typename T> 136 struct weak_ordering_base { 137 ABSL_COMPARE_INLINE_BASECLASS_DECL(less); 138 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 139 ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); 140 }; 141 142 template <typename T> 143 struct strong_ordering_base { 144 ABSL_COMPARE_INLINE_BASECLASS_DECL(less); 145 ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); 146 ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); 147 ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); 148 }; 149 150 } // namespace compare_internal 151 152 class weak_equality 153 : public compare_internal::weak_equality_base<weak_equality> { weak_equality(compare_internal::eq v)154 explicit constexpr weak_equality(compare_internal::eq v) noexcept 155 : value_(static_cast<compare_internal::value_type>(v)) {} 156 friend struct compare_internal::weak_equality_base<weak_equality>; 157 158 public: 159 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent); 160 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent); 161 162 // Comparisons 163 friend constexpr bool operator==( 164 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 165 return v.value_ == 0; 166 } 167 friend constexpr bool operator!=( 168 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 169 return v.value_ != 0; 170 } 171 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 172 weak_equality v) noexcept { 173 return 0 == v.value_; 174 } 175 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 176 weak_equality v) noexcept { 177 return 0 != v.value_; 178 } 179 friend constexpr bool operator==(weak_equality v1, 180 weak_equality v2) noexcept { 181 return v1.value_ == v2.value_; 182 } 183 friend constexpr bool operator!=(weak_equality v1, 184 weak_equality v2) noexcept { 185 return v1.value_ != v2.value_; 186 } 187 188 private: 189 compare_internal::value_type value_; 190 }; 191 ABSL_COMPARE_INLINE_INIT(weak_equality, equivalent, 192 compare_internal::eq::equivalent); 193 ABSL_COMPARE_INLINE_INIT(weak_equality, nonequivalent, 194 compare_internal::eq::nonequivalent); 195 196 class strong_equality 197 : public compare_internal::strong_equality_base<strong_equality> { 198 explicit constexpr strong_equality(compare_internal::eq v) noexcept 199 : value_(static_cast<compare_internal::value_type>(v)) {} 200 friend struct compare_internal::strong_equality_base<strong_equality>; 201 202 public: 203 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal); 204 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal); 205 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent); 206 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent); 207 208 // Conversion 209 constexpr operator weak_equality() const noexcept { // NOLINT 210 return value_ == 0 ? weak_equality::equivalent 211 : weak_equality::nonequivalent; 212 } 213 // Comparisons 214 friend constexpr bool operator==( 215 strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 216 return v.value_ == 0; 217 } 218 friend constexpr bool operator!=( 219 strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { 220 return v.value_ != 0; 221 } 222 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 223 strong_equality v) noexcept { 224 return 0 == v.value_; 225 } 226 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 227 strong_equality v) noexcept { 228 return 0 != v.value_; 229 } 230 friend constexpr bool operator==(strong_equality v1, 231 strong_equality v2) noexcept { 232 return v1.value_ == v2.value_; 233 } 234 friend constexpr bool operator!=(strong_equality v1, 235 strong_equality v2) noexcept { 236 return v1.value_ != v2.value_; 237 } 238 239 private: 240 compare_internal::value_type value_; 241 }; 242 ABSL_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal); 243 ABSL_COMPARE_INLINE_INIT(strong_equality, nonequal, 244 compare_internal::eq::nonequal); 245 ABSL_COMPARE_INLINE_INIT(strong_equality, equivalent, 246 compare_internal::eq::equivalent); 247 ABSL_COMPARE_INLINE_INIT(strong_equality, nonequivalent, 248 compare_internal::eq::nonequivalent); 249 250 class partial_ordering 251 : public compare_internal::partial_ordering_base<partial_ordering> { 252 explicit constexpr partial_ordering(compare_internal::eq v) noexcept 253 : value_(static_cast<compare_internal::value_type>(v)) {} 254 explicit constexpr partial_ordering(compare_internal::ord v) noexcept 255 : value_(static_cast<compare_internal::value_type>(v)) {} 256 explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept 257 : value_(static_cast<compare_internal::value_type>(v)) {} 258 friend struct compare_internal::partial_ordering_base<partial_ordering>; 259 260 constexpr bool is_ordered() const noexcept { 261 return value_ != 262 compare_internal::value_type(compare_internal::ncmp::unordered); 263 } 264 265 public: 266 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less); 267 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent); 268 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater); 269 ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered); 270 271 // Conversion 272 constexpr operator weak_equality() const noexcept { // NOLINT 273 return value_ == 0 ? weak_equality::equivalent 274 : weak_equality::nonequivalent; 275 } 276 // Comparisons 277 friend constexpr bool operator==( 278 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 279 return v.is_ordered() && v.value_ == 0; 280 } 281 friend constexpr bool operator!=( 282 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 283 return !v.is_ordered() || v.value_ != 0; 284 } 285 friend constexpr bool operator<( 286 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 287 return v.is_ordered() && v.value_ < 0; 288 } 289 friend constexpr bool operator<=( 290 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 291 return v.is_ordered() && v.value_ <= 0; 292 } 293 friend constexpr bool operator>( 294 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 295 return v.is_ordered() && v.value_ > 0; 296 } 297 friend constexpr bool operator>=( 298 partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 299 return v.is_ordered() && v.value_ >= 0; 300 } 301 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 302 partial_ordering v) noexcept { 303 return v.is_ordered() && 0 == v.value_; 304 } 305 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 306 partial_ordering v) noexcept { 307 return !v.is_ordered() || 0 != v.value_; 308 } 309 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, 310 partial_ordering v) noexcept { 311 return v.is_ordered() && 0 < v.value_; 312 } 313 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, 314 partial_ordering v) noexcept { 315 return v.is_ordered() && 0 <= v.value_; 316 } 317 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, 318 partial_ordering v) noexcept { 319 return v.is_ordered() && 0 > v.value_; 320 } 321 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, 322 partial_ordering v) noexcept { 323 return v.is_ordered() && 0 >= v.value_; 324 } 325 friend constexpr bool operator==(partial_ordering v1, 326 partial_ordering v2) noexcept { 327 return v1.value_ == v2.value_; 328 } 329 friend constexpr bool operator!=(partial_ordering v1, 330 partial_ordering v2) noexcept { 331 return v1.value_ != v2.value_; 332 } 333 334 private: 335 compare_internal::value_type value_; 336 }; 337 ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less); 338 ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent, 339 compare_internal::eq::equivalent); 340 ABSL_COMPARE_INLINE_INIT(partial_ordering, greater, 341 compare_internal::ord::greater); 342 ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered, 343 compare_internal::ncmp::unordered); 344 345 class weak_ordering 346 : public compare_internal::weak_ordering_base<weak_ordering> { 347 explicit constexpr weak_ordering(compare_internal::eq v) noexcept 348 : value_(static_cast<compare_internal::value_type>(v)) {} 349 explicit constexpr weak_ordering(compare_internal::ord v) noexcept 350 : value_(static_cast<compare_internal::value_type>(v)) {} 351 friend struct compare_internal::weak_ordering_base<weak_ordering>; 352 353 public: 354 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less); 355 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent); 356 ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater); 357 358 // Conversions 359 constexpr operator weak_equality() const noexcept { // NOLINT 360 return value_ == 0 ? weak_equality::equivalent 361 : weak_equality::nonequivalent; 362 } 363 constexpr operator partial_ordering() const noexcept { // NOLINT 364 return value_ == 0 ? partial_ordering::equivalent 365 : (value_ < 0 ? partial_ordering::less 366 : partial_ordering::greater); 367 } 368 // Comparisons 369 friend constexpr bool operator==( 370 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 371 return v.value_ == 0; 372 } 373 friend constexpr bool operator!=( 374 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 375 return v.value_ != 0; 376 } 377 friend constexpr bool operator<( 378 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 379 return v.value_ < 0; 380 } 381 friend constexpr bool operator<=( 382 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 383 return v.value_ <= 0; 384 } 385 friend constexpr bool operator>( 386 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 387 return v.value_ > 0; 388 } 389 friend constexpr bool operator>=( 390 weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 391 return v.value_ >= 0; 392 } 393 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 394 weak_ordering v) noexcept { 395 return 0 == v.value_; 396 } 397 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 398 weak_ordering v) noexcept { 399 return 0 != v.value_; 400 } 401 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, 402 weak_ordering v) noexcept { 403 return 0 < v.value_; 404 } 405 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, 406 weak_ordering v) noexcept { 407 return 0 <= v.value_; 408 } 409 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, 410 weak_ordering v) noexcept { 411 return 0 > v.value_; 412 } 413 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, 414 weak_ordering v) noexcept { 415 return 0 >= v.value_; 416 } 417 friend constexpr bool operator==(weak_ordering v1, 418 weak_ordering v2) noexcept { 419 return v1.value_ == v2.value_; 420 } 421 friend constexpr bool operator!=(weak_ordering v1, 422 weak_ordering v2) noexcept { 423 return v1.value_ != v2.value_; 424 } 425 426 private: 427 compare_internal::value_type value_; 428 }; 429 ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less); 430 ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent, 431 compare_internal::eq::equivalent); 432 ABSL_COMPARE_INLINE_INIT(weak_ordering, greater, 433 compare_internal::ord::greater); 434 435 class strong_ordering 436 : public compare_internal::strong_ordering_base<strong_ordering> { 437 explicit constexpr strong_ordering(compare_internal::eq v) noexcept 438 : value_(static_cast<compare_internal::value_type>(v)) {} 439 explicit constexpr strong_ordering(compare_internal::ord v) noexcept 440 : value_(static_cast<compare_internal::value_type>(v)) {} 441 friend struct compare_internal::strong_ordering_base<strong_ordering>; 442 443 public: 444 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less); 445 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal); 446 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent); 447 ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater); 448 449 // Conversions 450 constexpr operator weak_equality() const noexcept { // NOLINT 451 return value_ == 0 ? weak_equality::equivalent 452 : weak_equality::nonequivalent; 453 } 454 constexpr operator strong_equality() const noexcept { // NOLINT 455 return value_ == 0 ? strong_equality::equal : strong_equality::nonequal; 456 } 457 constexpr operator partial_ordering() const noexcept { // NOLINT 458 return value_ == 0 ? partial_ordering::equivalent 459 : (value_ < 0 ? partial_ordering::less 460 : partial_ordering::greater); 461 } 462 constexpr operator weak_ordering() const noexcept { // NOLINT 463 return value_ == 0 464 ? weak_ordering::equivalent 465 : (value_ < 0 ? weak_ordering::less : weak_ordering::greater); 466 } 467 // Comparisons 468 friend constexpr bool operator==( 469 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 470 return v.value_ == 0; 471 } 472 friend constexpr bool operator!=( 473 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 474 return v.value_ != 0; 475 } 476 friend constexpr bool operator<( 477 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 478 return v.value_ < 0; 479 } 480 friend constexpr bool operator<=( 481 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 482 return v.value_ <= 0; 483 } 484 friend constexpr bool operator>( 485 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 486 return v.value_ > 0; 487 } 488 friend constexpr bool operator>=( 489 strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { 490 return v.value_ >= 0; 491 } 492 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, 493 strong_ordering v) noexcept { 494 return 0 == v.value_; 495 } 496 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, 497 strong_ordering v) noexcept { 498 return 0 != v.value_; 499 } 500 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, 501 strong_ordering v) noexcept { 502 return 0 < v.value_; 503 } 504 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, 505 strong_ordering v) noexcept { 506 return 0 <= v.value_; 507 } 508 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, 509 strong_ordering v) noexcept { 510 return 0 > v.value_; 511 } 512 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, 513 strong_ordering v) noexcept { 514 return 0 >= v.value_; 515 } 516 friend constexpr bool operator==(strong_ordering v1, 517 strong_ordering v2) noexcept { 518 return v1.value_ == v2.value_; 519 } 520 friend constexpr bool operator!=(strong_ordering v1, 521 strong_ordering v2) noexcept { 522 return v1.value_ != v2.value_; 523 } 524 525 private: 526 compare_internal::value_type value_; 527 }; 528 ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less); 529 ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal); 530 ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent, 531 compare_internal::eq::equivalent); 532 ABSL_COMPARE_INLINE_INIT(strong_ordering, greater, 533 compare_internal::ord::greater); 534 535 #undef ABSL_COMPARE_INLINE_BASECLASS_DECL 536 #undef ABSL_COMPARE_INLINE_SUBCLASS_DECL 537 #undef ABSL_COMPARE_INLINE_INIT 538 539 namespace compare_internal { 540 // We also provide these comparator adapter functions for internal absl use. 541 542 // Helper functions to do a boolean comparison of two keys given a boolean 543 // or three-way comparator. 544 // SFINAE prevents implicit conversions to bool (such as from int). 545 template <typename Bool, 546 absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0> 547 constexpr bool compare_result_as_less_than(const Bool r) { return r; } 548 constexpr bool compare_result_as_less_than(const absl::weak_ordering r) { 549 return r < 0; 550 } 551 552 template <typename Compare, typename K, typename LK> 553 constexpr bool do_less_than_comparison(const Compare &compare, const K &x, 554 const LK &y) { 555 return compare_result_as_less_than(compare(x, y)); 556 } 557 558 // Helper functions to do a three-way comparison of two keys given a boolean or 559 // three-way comparator. 560 // SFINAE prevents implicit conversions to int (such as from bool). 561 template <typename Int, 562 absl::enable_if_t<std::is_same<int, Int>::value, int> = 0> 563 constexpr absl::weak_ordering compare_result_as_ordering(const Int c) { 564 return c < 0 ? absl::weak_ordering::less 565 : c == 0 ? absl::weak_ordering::equivalent 566 : absl::weak_ordering::greater; 567 } 568 constexpr absl::weak_ordering compare_result_as_ordering( 569 const absl::weak_ordering c) { 570 return c; 571 } 572 573 template < 574 typename Compare, typename K, typename LK, 575 absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare( 576 const K &, const LK &)>>::value, 577 int> = 0> 578 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, 579 const K &x, const LK &y) { 580 return compare_result_as_ordering(compare(x, y)); 581 } 582 template < 583 typename Compare, typename K, typename LK, 584 absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare( 585 const K &, const LK &)>>::value, 586 int> = 0> 587 constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, 588 const K &x, const LK &y) { 589 return compare(x, y) ? absl::weak_ordering::less 590 : compare(y, x) ? absl::weak_ordering::greater 591 : absl::weak_ordering::equivalent; 592 } 593 594 } // namespace compare_internal 595 ABSL_NAMESPACE_END 596 } // namespace absl 597 598 #endif // ABSL_TYPES_COMPARE_H_ 599