Fix the implementation of OnlyLiteralZero (#1420)

This patch changes the implementation of OnlyLiteralZero to only fail if the second overload is chosen, instead of failing during overload resolution.

This patch cherry-picks 2de126cc5826a8d464270ead65a7a9a7b012b741.

Fixes #1419
diff --git a/absl/base/config.h b/absl/base/config.h
index 573c9fd..0631ab6 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -112,7 +112,7 @@
 // LTS releases can be obtained from
 // https://github.com/abseil/abseil-cpp/releases.
 #define ABSL_LTS_RELEASE_VERSION 20230125
-#define ABSL_LTS_RELEASE_PATCH_LEVEL 1
+#define ABSL_LTS_RELEASE_PATCH_LEVEL 2
 
 // Helper macro to convert a CPP variable to a string literal.
 #define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
diff --git a/absl/types/compare.h b/absl/types/compare.h
index 78aa26d..1a965e9 100644
--- a/absl/types/compare.h
+++ b/absl/types/compare.h
@@ -44,29 +44,28 @@
 
 using value_type = int8_t;
 
-template <typename T>
-struct Fail {
-  static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
-};
+class OnlyLiteralZero {
+  // A private type which cannot be named to explicitly cast to it.
+  struct MatchLiteralZero;
 
-// We need the NullPtrT template to avoid triggering the modernize-use-nullptr
-// ClangTidy warning in user code.
-template <typename NullPtrT = std::nullptr_t>
-struct OnlyLiteralZero {
-  constexpr OnlyLiteralZero(NullPtrT) noexcept {}  // NOLINT
+ public:
+  // Accept only literal zero since it can be implicitly converted to a pointer
+  // type. nullptr constants will be caught by the other constructor which
+  // accepts a nullptr_t.
+  constexpr OnlyLiteralZero(MatchLiteralZero *) noexcept {}  // NOLINT
 
   // Fails compilation when `nullptr` or integral type arguments other than
   // `int` are passed. This constructor doesn't accept `int` because literal `0`
   // has type `int`. Literal `0` arguments will be implicitly converted to
   // `std::nullptr_t` and accepted by the above constructor, while other `int`
   // arguments will fail to be converted and cause compilation failure.
-  template <
-      typename T,
-      typename = typename std::enable_if<
-          std::is_same<T, std::nullptr_t>::value ||
-          (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type,
-      typename = typename Fail<T>::type>
-  OnlyLiteralZero(T);  // NOLINT
+  template <typename T, typename = typename std::enable_if<
+                            std::is_same<T, std::nullptr_t>::value ||
+                            (std::is_integral<T>::value &&
+                             !std::is_same<T, int>::value)>::type>
+  OnlyLiteralZero(T) {  // NOLINT
+    static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
+  }
 };
 
 enum class eq : value_type {
@@ -163,18 +162,18 @@
 
   // Comparisons
   friend constexpr bool operator==(
-      weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_equality v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ == 0;
   }
   friend constexpr bool operator!=(
-      weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_equality v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ != 0;
   }
-  friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
                                    weak_equality v) noexcept {
     return 0 == v.value_;
   }
-  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
                                    weak_equality v) noexcept {
     return 0 != v.value_;
   }
@@ -214,18 +213,18 @@
   }
   // Comparisons
   friend constexpr bool operator==(
-      strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_equality v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ == 0;
   }
   friend constexpr bool operator!=(
-      strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_equality v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ != 0;
   }
-  friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
                                    strong_equality v) noexcept {
     return 0 == v.value_;
   }
-  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
                                    strong_equality v) noexcept {
     return 0 != v.value_;
   }
@@ -277,50 +276,50 @@
   }
   // Comparisons
   friend constexpr bool operator==(
-      partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.is_ordered() && v.value_ == 0;
   }
   friend constexpr bool operator!=(
-      partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return !v.is_ordered() || v.value_ != 0;
   }
   friend constexpr bool operator<(
-      partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.is_ordered() && v.value_ < 0;
   }
   friend constexpr bool operator<=(
-      partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.is_ordered() && v.value_ <= 0;
   }
   friend constexpr bool operator>(
-      partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.is_ordered() && v.value_ > 0;
   }
   friend constexpr bool operator>=(
-      partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.is_ordered() && v.value_ >= 0;
   }
-  friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
                                    partial_ordering v) noexcept {
     return v.is_ordered() && 0 == v.value_;
   }
-  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
                                    partial_ordering v) noexcept {
     return !v.is_ordered() || 0 != v.value_;
   }
-  friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
                                   partial_ordering v) noexcept {
     return v.is_ordered() && 0 < v.value_;
   }
-  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
                                    partial_ordering v) noexcept {
     return v.is_ordered() && 0 <= v.value_;
   }
-  friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
                                   partial_ordering v) noexcept {
     return v.is_ordered() && 0 > v.value_;
   }
-  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
                                    partial_ordering v) noexcept {
     return v.is_ordered() && 0 >= v.value_;
   }
@@ -369,50 +368,50 @@
   }
   // Comparisons
   friend constexpr bool operator==(
-      weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ == 0;
   }
   friend constexpr bool operator!=(
-      weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ != 0;
   }
   friend constexpr bool operator<(
-      weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ < 0;
   }
   friend constexpr bool operator<=(
-      weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ <= 0;
   }
   friend constexpr bool operator>(
-      weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ > 0;
   }
   friend constexpr bool operator>=(
-      weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ >= 0;
   }
-  friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
                                    weak_ordering v) noexcept {
     return 0 == v.value_;
   }
-  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
                                    weak_ordering v) noexcept {
     return 0 != v.value_;
   }
-  friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
                                   weak_ordering v) noexcept {
     return 0 < v.value_;
   }
-  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
                                    weak_ordering v) noexcept {
     return 0 <= v.value_;
   }
-  friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
                                   weak_ordering v) noexcept {
     return 0 > v.value_;
   }
-  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
                                    weak_ordering v) noexcept {
     return 0 >= v.value_;
   }
@@ -468,50 +467,50 @@
   }
   // Comparisons
   friend constexpr bool operator==(
-      strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ == 0;
   }
   friend constexpr bool operator!=(
-      strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ != 0;
   }
   friend constexpr bool operator<(
-      strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ < 0;
   }
   friend constexpr bool operator<=(
-      strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ <= 0;
   }
   friend constexpr bool operator>(
-      strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ > 0;
   }
   friend constexpr bool operator>=(
-      strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+      strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
     return v.value_ >= 0;
   }
-  friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
                                    strong_ordering v) noexcept {
     return 0 == v.value_;
   }
-  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
                                    strong_ordering v) noexcept {
     return 0 != v.value_;
   }
-  friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
                                   strong_ordering v) noexcept {
     return 0 < v.value_;
   }
-  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
                                    strong_ordering v) noexcept {
     return 0 <= v.value_;
   }
-  friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
                                   strong_ordering v) noexcept {
     return 0 > v.value_;
   }
-  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+  friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
                                    strong_ordering v) noexcept {
     return 0 >= v.value_;
   }