Skip to content

Commit

Permalink
Change implementation of OnlyLiteralZero to only fail if the second o…
Browse files Browse the repository at this point in the history
…verload is chosen, not in overload resolution.

PiperOrigin-RevId: 508031321
Change-Id: I6981371fbc6498047babe3468f3343090f8bda47
  • Loading branch information
Abseil Team authored and Copybara-Service committed Feb 8, 2023
1 parent f8fa267 commit 2de126c
Showing 1 changed file with 59 additions and 60 deletions.
119 changes: 59 additions & 60 deletions absl/types/compare.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,28 @@ namespace compare_internal {

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 {
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -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_;
}
Expand Down

0 comments on commit 2de126c

Please sign in to comment.