Commit b971ac52 by Derek Mauro Committed by GitHub

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 2de126cc.

Fixes #1419
parent c8a2f925
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
// LTS releases can be obtained from // LTS releases can be obtained from
// https://github.com/abseil/abseil-cpp/releases. // https://github.com/abseil/abseil-cpp/releases.
#define ABSL_LTS_RELEASE_VERSION 20230125 #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. // Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x #define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
......
...@@ -44,29 +44,28 @@ namespace compare_internal { ...@@ -44,29 +44,28 @@ namespace compare_internal {
using value_type = int8_t; using value_type = int8_t;
template <typename T> class OnlyLiteralZero {
struct Fail { // A private type which cannot be named to explicitly cast to it.
static_assert(sizeof(T) < 0, "Only literal `0` is allowed."); struct MatchLiteralZero;
};
// We need the NullPtrT template to avoid triggering the modernize-use-nullptr public:
// ClangTidy warning in user code. // Accept only literal zero since it can be implicitly converted to a pointer
template <typename NullPtrT = std::nullptr_t> // type. nullptr constants will be caught by the other constructor which
struct OnlyLiteralZero { // accepts a nullptr_t.
constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT constexpr OnlyLiteralZero(MatchLiteralZero *) noexcept {} // NOLINT
// Fails compilation when `nullptr` or integral type arguments other than // Fails compilation when `nullptr` or integral type arguments other than
// `int` are passed. This constructor doesn't accept `int` because literal `0` // `int` are passed. This constructor doesn't accept `int` because literal `0`
// has type `int`. Literal `0` arguments will be implicitly converted to // has type `int`. Literal `0` arguments will be implicitly converted to
// `std::nullptr_t` and accepted by the above constructor, while other `int` // `std::nullptr_t` and accepted by the above constructor, while other `int`
// arguments will fail to be converted and cause compilation failure. // arguments will fail to be converted and cause compilation failure.
template < template <typename T, typename = typename std::enable_if<
typename T,
typename = typename std::enable_if<
std::is_same<T, std::nullptr_t>::value || std::is_same<T, std::nullptr_t>::value ||
(std::is_integral<T>::value && !std::is_same<T, int>::value)>::type, (std::is_integral<T>::value &&
typename = typename Fail<T>::type> !std::is_same<T, int>::value)>::type>
OnlyLiteralZero(T); // NOLINT OnlyLiteralZero(T) { // NOLINT
static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
}
}; };
enum class eq : value_type { enum class eq : value_type {
...@@ -163,18 +162,18 @@ class weak_equality ...@@ -163,18 +162,18 @@ class weak_equality
// Comparisons // Comparisons
friend constexpr bool operator==( friend constexpr bool operator==(
weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { weak_equality v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ == 0; return v.value_ == 0;
} }
friend constexpr bool operator!=( friend constexpr bool operator!=(
weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { weak_equality v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ != 0; return v.value_ != 0;
} }
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
weak_equality v) noexcept { weak_equality v) noexcept {
return 0 == v.value_; return 0 == v.value_;
} }
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
weak_equality v) noexcept { weak_equality v) noexcept {
return 0 != v.value_; return 0 != v.value_;
} }
...@@ -214,18 +213,18 @@ class strong_equality ...@@ -214,18 +213,18 @@ class strong_equality
} }
// Comparisons // Comparisons
friend constexpr bool operator==( friend constexpr bool operator==(
strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { strong_equality v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ == 0; return v.value_ == 0;
} }
friend constexpr bool operator!=( friend constexpr bool operator!=(
strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept { strong_equality v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ != 0; return v.value_ != 0;
} }
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
strong_equality v) noexcept { strong_equality v) noexcept {
return 0 == v.value_; return 0 == v.value_;
} }
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
strong_equality v) noexcept { strong_equality v) noexcept {
return 0 != v.value_; return 0 != v.value_;
} }
...@@ -277,50 +276,50 @@ class partial_ordering ...@@ -277,50 +276,50 @@ class partial_ordering
} }
// Comparisons // Comparisons
friend constexpr bool operator==( 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; return v.is_ordered() && v.value_ == 0;
} }
friend constexpr bool operator!=( 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; return !v.is_ordered() || v.value_ != 0;
} }
friend constexpr bool operator<( 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; return v.is_ordered() && v.value_ < 0;
} }
friend constexpr bool operator<=( 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; return v.is_ordered() && v.value_ <= 0;
} }
friend constexpr bool operator>( 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; return v.is_ordered() && v.value_ > 0;
} }
friend constexpr bool operator>=( 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; 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 { partial_ordering v) noexcept {
return v.is_ordered() && 0 == v.value_; 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 { partial_ordering v) noexcept {
return !v.is_ordered() || 0 != v.value_; 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 { partial_ordering v) noexcept {
return v.is_ordered() && 0 < v.value_; 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 { partial_ordering v) noexcept {
return v.is_ordered() && 0 <= v.value_; 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 { partial_ordering v) noexcept {
return v.is_ordered() && 0 > v.value_; 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 { partial_ordering v) noexcept {
return v.is_ordered() && 0 >= v.value_; return v.is_ordered() && 0 >= v.value_;
} }
...@@ -369,50 +368,50 @@ class weak_ordering ...@@ -369,50 +368,50 @@ class weak_ordering
} }
// Comparisons // Comparisons
friend constexpr bool operator==( friend constexpr bool operator==(
weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ == 0; return v.value_ == 0;
} }
friend constexpr bool operator!=( friend constexpr bool operator!=(
weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ != 0; return v.value_ != 0;
} }
friend constexpr bool operator<( friend constexpr bool operator<(
weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ < 0; return v.value_ < 0;
} }
friend constexpr bool operator<=( friend constexpr bool operator<=(
weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ <= 0; return v.value_ <= 0;
} }
friend constexpr bool operator>( friend constexpr bool operator>(
weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ > 0; return v.value_ > 0;
} }
friend constexpr bool operator>=( friend constexpr bool operator>=(
weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ >= 0; return v.value_ >= 0;
} }
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 == v.value_; return 0 == v.value_;
} }
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 != v.value_; return 0 != v.value_;
} }
friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 < v.value_; return 0 < v.value_;
} }
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 <= v.value_; return 0 <= v.value_;
} }
friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 > v.value_; return 0 > v.value_;
} }
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept { weak_ordering v) noexcept {
return 0 >= v.value_; return 0 >= v.value_;
} }
...@@ -468,50 +467,50 @@ class strong_ordering ...@@ -468,50 +467,50 @@ class strong_ordering
} }
// Comparisons // Comparisons
friend constexpr bool operator==( friend constexpr bool operator==(
strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ == 0; return v.value_ == 0;
} }
friend constexpr bool operator!=( friend constexpr bool operator!=(
strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ != 0; return v.value_ != 0;
} }
friend constexpr bool operator<( friend constexpr bool operator<(
strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ < 0; return v.value_ < 0;
} }
friend constexpr bool operator<=( friend constexpr bool operator<=(
strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ <= 0; return v.value_ <= 0;
} }
friend constexpr bool operator>( friend constexpr bool operator>(
strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ > 0; return v.value_ > 0;
} }
friend constexpr bool operator>=( friend constexpr bool operator>=(
strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept { strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ >= 0; return v.value_ >= 0;
} }
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 == v.value_; return 0 == v.value_;
} }
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 != v.value_; return 0 != v.value_;
} }
friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 < v.value_; return 0 < v.value_;
} }
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 <= v.value_; return 0 <= v.value_;
} }
friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 > v.value_; return 0 > v.value_;
} }
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept { strong_ordering v) noexcept {
return 0 >= v.value_; return 0 >= v.value_;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment