https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104606
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |ASSIGNED
Assignee|unassigned at gcc dot gnu.org |redi at gcc dot gnu.org
--- Comment #12 from Jonathan Wakely <redi at gcc dot gnu.org> ---
std::optional's spaceship operator currently looks like this:
template<typename _Tp, typename _Up>
requires (!__is_optional_v<_Up>)
&& three_way_comparable_with<_Tp, _Up>
constexpr compare_three_way_result_t<_Tp, _Up>
operator<=>(const optional<_Tp>& __x, const _Up& __v)
As Jakub noted, if we revert the LWG 3566 change it works:
template<typename _Tp, three_way_comparable_with<_Tp> _Up>
constexpr compare_three_way_result_t<_Tp, _Up>
operator<=>(const optional<_Tp>& __x, const _Up& __v)
We can rewrite that to this, which should be exactly equivalent, and it still
works:
template<typename _Tp, typename _Up>
requires three_way_comparable_with<_Up, _Tp>
constexpr compare_three_way_result_t<_Tp, _Up>
operator<=>(const optional<_Tp>& __x, const _Up& __v)
and then we can add the !is-optional<U> constraint back in:
template<typename _Tp, typename _Up>
requires
(!__is_optional_v<_Up>) &&
three_way_comparable_with<_Up, _Tp>
constexpr compare_three_way_result_t<_Tp, _Up>
operator<=>(const optional<_Tp>& __x, const _Up& __v)
And it still works! The only difference is:
three_way_comparable_with<_Up, _Tp>
vs
three_way_comparable_with<_Tp, _Up>
This should not matter, but it does.
So there definitely seems to be a front end bug here, but at least there's an
easy fix for the library.