summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2024-06-26 08:13:11 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2024-06-26 08:14:50 -0700
commitc98bd9c8840f9ded87cf1fd1238455468d325628 (patch)
tree92d3514de1b1ffb48db9faf17ddaf59cba6ebfa2
parent3ff94461f8cf00fa976225f3b020e65268e24626 (diff)
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
-rw-r--r--absl/strings/BUILD.bazel2
-rw-r--r--absl/strings/CMakeLists.txt1
-rw-r--r--absl/strings/cord.h33
-rw-r--r--absl/strings/cord_test.cc26
4 files changed, 62 insertions, 0 deletions
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<const CordzInfo*> 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.