From c98bd9c8840f9ded87cf1fd1238455468d325628 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 26 Jun 2024 08:13:11 -0700 Subject: Three-way comparison spaceship <=> operators for Cord. This is portable because cord already has `operator<` etc., which will be unaffected. This just allows C++ >= 20 users to explicitly call `operator<=>`. PiperOrigin-RevId: 646951415 Change-Id: I1432e224bd5dc09b99d56a1d27e95078463adf45 --- absl/strings/BUILD.bazel | 2 ++ absl/strings/CMakeLists.txt | 1 + absl/strings/cord.h | 33 +++++++++++++++++++++++++++++++++ absl/strings/cord_test.cc | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 48793edd..9bffae61 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -600,6 +600,7 @@ cc_library( "//absl/functional:function_ref", "//absl/meta:type_traits", "//absl/numeric:bits", + "//absl/types:compare", "//absl/types:optional", "//absl/types:span", ], @@ -925,6 +926,7 @@ cc_test( "//absl/log", "//absl/log:check", "//absl/random", + "//absl/types:compare", "//absl/types:optional", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 4696eb30..4a84dbbd 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -705,6 +705,7 @@ absl_cc_library( absl::compressed_tuple absl::config absl::container_memory + absl::compare absl::core_headers absl::crc_cord_state absl::endian diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 0d8d7007..c68b6f10 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -96,6 +96,7 @@ #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/string_constant.h" #include "absl/strings/string_view.h" +#include "absl/types/compare.h" #include "absl/types/optional.h" namespace absl { @@ -849,6 +850,38 @@ class Cord { friend bool operator==(const Cord& lhs, const Cord& rhs); friend bool operator==(const Cord& lhs, absl::string_view rhs); +#ifdef __cpp_impl_three_way_comparison + + // Cords support comparison with other Cords and string_views via operator< + // and others; here we provide a wrapper for the C++20 three-way comparison + // <=> operator. + + static inline std::strong_ordering ConvertCompareResultToStrongOrdering( + int c) { + if (c == 0) { + return std::strong_ordering::equal; + } else if (c < 0) { + return std::strong_ordering::less; + } else { + return std::strong_ordering::greater; + } + } + + friend inline std::strong_ordering operator<=>(const Cord& x, const Cord& y) { + return ConvertCompareResultToStrongOrdering(x.Compare(y)); + } + + friend inline std::strong_ordering operator<=>(const Cord& lhs, + absl::string_view rhs) { + return ConvertCompareResultToStrongOrdering(lhs.Compare(rhs)); + } + + friend inline std::strong_ordering operator<=>(absl::string_view lhs, + const Cord& rhs) { + return ConvertCompareResultToStrongOrdering(-rhs.Compare(lhs)); + } +#endif + friend absl::Nullable GetCordzInfoForTesting( const Cord& cord); diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index c4a7288a..eaf6d719 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc @@ -60,6 +60,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" +#include "absl/types/compare.h" #include "absl/types/optional.h" // convenience local constants @@ -3283,6 +3284,31 @@ TEST(CrcCordTest, ChecksummedEmptyCordEstimateMemoryUsage) { EXPECT_NE(cord.EstimatedMemoryUsage(), 0); } +TEST(CordThreeWayComparisonTest, CompareCords) { +#ifndef __cpp_impl_three_way_comparison + GTEST_SKIP() << "C++20 three-way <=> comparison not supported"; +#else + EXPECT_EQ(absl::Cord("a") <=> absl::Cord("a"), std::strong_ordering::equal); + EXPECT_EQ(absl::Cord("aaaa") <=> absl::Cord("aaab"), + std::strong_ordering::less); + EXPECT_EQ(absl::Cord("baaa") <=> absl::Cord("a"), + std::strong_ordering::greater); +#endif +} + +TEST(CordThreeWayComparisonTest, CompareCordsAndStringViews) { +#ifndef __cpp_impl_three_way_comparison + GTEST_SKIP() << "C++20 three-way <=> comparison not supported"; +#else + EXPECT_EQ(absl::string_view("a") <=> absl::Cord("a"), + std::strong_ordering::equal); + EXPECT_EQ(absl::Cord("a") <=> absl::string_view("b"), + std::strong_ordering::less); + EXPECT_EQ(absl::string_view("b") <=> absl::Cord("a"), + std::strong_ordering::greater); +#endif +} + #if defined(GTEST_HAS_DEATH_TEST) && defined(ABSL_INTERNAL_CORD_HAVE_SANITIZER) // Returns an expected poison / uninitialized death message expression. -- cgit v1.2.3