Enable `operator==` for `StatusOr` only if the contained type is equality-comparable

PiperOrigin-RevId: 774693039
Change-Id: I915ce87aa37094d1596618cf2604d0bd98583218
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
index e986611..029fdee 100644
--- a/absl/status/internal/statusor_internal.h
+++ b/absl/status/internal/statusor_internal.h
@@ -46,6 +46,16 @@
 struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
     : std::true_type {};
 
+// Detects whether `T` is equality-comparable.
+template <typename T, typename = void>
+struct IsEqualityComparable : std::false_type {};
+
+template <typename T>
+struct IsEqualityComparable<
+    T, std::enable_if_t<std::is_convertible<
+           decltype(std::declval<T>() == std::declval<T>()),
+           bool>::value>> : std::true_type {};
+
 // Detects whether `T` is constructible or convertible from `StatusOr<U>`.
 template <typename T, typename U>
 using IsConstructibleOrConvertibleFromStatusOr =
diff --git a/absl/status/statusor.h b/absl/status/statusor.h
index 6142a2f..25c6288 100644
--- a/absl/status/statusor.h
+++ b/absl/status/statusor.h
@@ -607,7 +607,9 @@
 // operator==()
 //
 // This operator checks the equality of two `absl::StatusOr<T>` objects.
-template <typename T>
+template <typename T,
+          std::enable_if_t<internal_statusor::IsEqualityComparable<T>::value,
+                           int> = 0>
 bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
   if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
   return lhs.status() == rhs.status();
@@ -616,7 +618,9 @@
 // operator!=()
 //
 // This operator checks the inequality of two `absl::StatusOr<T>` objects.
-template <typename T>
+template <typename T,
+          std::enable_if_t<internal_statusor::IsEqualityComparable<T>::value,
+                           int> = 0>
 bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
   return !(lhs == rhs);
 }