From b971ac5250ea8de900eae9f95e06548d14cd95fe Mon Sep 17 00:00:00 2001 From: Derek Mauro <761129+derekmauro@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:58:21 -0400 Subject: 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 --- absl/base/config.h | 2 +- absl/types/compare.h | 119 +++++++++++++++++++++++++-------------------------- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/absl/base/config.h b/absl/base/config.h index 573c9fd7..0631ab60 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 78aa26de..1a965e97 100644 --- a/absl/types/compare.h +++ b/absl/types/compare.h @@ -44,29 +44,28 @@ namespace compare_internal { using value_type = int8_t; -template -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 -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::value || - (std::is_integral::value && !std::is_same::value)>::type, - typename = typename Fail::type> - OnlyLiteralZero(T); // NOLINT + template ::value || + (std::is_integral::value && + !std::is_same::value)>::type> + OnlyLiteralZero(T) { // NOLINT + static_assert(sizeof(T) < 0, "Only literal `0` is allowed."); + } }; enum class eq : value_type { @@ -163,18 +162,18 @@ class weak_equality // 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 @@ class strong_equality } // 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 @@ class partial_ordering } // 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 @@ class weak_ordering } // 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 @@ class strong_ordering } // 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_; } -- cgit v1.2.3