Skip to content

Commit

Permalink
Avoid SFINAE in <=> using a lambda. (#549)
Browse files Browse the repository at this point in the history
Thanks to https://github.com/ned14 for the concept/SFINAE lesson.
  • Loading branch information
jbcoe authored Feb 13, 2025
1 parent 71a179c commit a1751f0
Showing 1 changed file with 23 additions and 17 deletions.
40 changes: 23 additions & 17 deletions indirect.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,16 +386,6 @@ class indirect {
return *lhs == *rhs;
}

template <class U, class AA>
[[nodiscard]] friend constexpr auto operator<=>(const indirect<T, A>& lhs,
const indirect<U, AA>& rhs)
-> detail::synth_three_way_result<T, U> {
if (lhs.valueless_after_move() || rhs.valueless_after_move()) {
return !lhs.valueless_after_move() <=> !rhs.valueless_after_move();
}
return detail::synth_three_way(*lhs, *rhs);
}

template <class U>
[[nodiscard]] friend constexpr bool operator==(const indirect<T, A>& lhs,
const U& rhs)
Expand All @@ -407,15 +397,31 @@ class indirect {
return *lhs == rhs;
}

template <class U>
template <class U, class AA>
[[nodiscard]] friend constexpr auto operator<=>(const indirect<T, A>& lhs,
const U& rhs)
-> detail::synth_three_way_result<
T, std::enable_if_t<!is_indirect_v<U>, U>> {
if (lhs.valueless_after_move()) {
return std::strong_ordering::less;
const indirect<U, AA>& rhs)
-> detail::synth_three_way_result<T, U> {
if (lhs.valueless_after_move() || rhs.valueless_after_move()) {
return !lhs.valueless_after_move() <=> !rhs.valueless_after_move();
}
return detail::synth_three_way(*lhs, rhs);
return detail::synth_three_way(*lhs, *rhs);
}

template <class U>
[[nodiscard]] friend constexpr auto operator<=>(const indirect<T, A>& lhs,
const U& rhs) -> auto
requires(!is_indirect_v<U>)
{
// Define and call a lambda to allow requirements to be checked before
// the return type is determined.
// This avoids a recursive check inside __partially_ordered_with.
return [](const auto& lhs,
const auto& rhs) -> detail::synth_three_way_result<T, U> {
if (lhs.valueless_after_move()) {
return std::strong_ordering::less;
}
return detail::synth_three_way(*lhs, rhs);
}(lhs, rhs);
}

private:
Expand Down

0 comments on commit a1751f0

Please sign in to comment.