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
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 48793ed..9bffae6 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -600,6 +600,7 @@
         "//absl/functional:function_ref",
         "//absl/meta:type_traits",
         "//absl/numeric:bits",
+        "//absl/types:compare",
         "//absl/types:optional",
         "//absl/types:span",
     ],
@@ -925,6 +926,7 @@
         "//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 4696eb3..4a84dbb 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -705,6 +705,7 @@
     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 0d8d700..c68b6f1 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 @@
   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 c4a7288..eaf6d71 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 @@
   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.