This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
Section: 26.6.4.3 [range.iota.iterator], 26.7.9.3 [range.transform.iterator], 26.7.22.3 [range.elements.iterator] Status: C++20 Submitter: Jonathan Wakely Opened: 2020-02-07 Last modified: 2021-02-25
Priority: 0
View all other issues in [range.iota.iterator].
View all issues with C++20 status.
Discussion:
26.6.4.3 [range.iota.iterator] and 26.7.9.3 [range.transform.iterator] and 26.7.22.3 [range.elements.iterator] all declare operator<=> similar to this:
friend constexpr compare_three_way_result_t<W> operator<=>( const iterator& x, const iterator& y) requires totally_ordered<W> && three_way_comparable<W>;
Similar to issue 3347 and issue 3387, this is ill-formed if three_way_comparable<W> is not satisfied, because compare_three_way_result_t<W> is invalid. This declaration is instantiated when the enclosing iterator type is instantiated, making any use of iota_view<W, B>::iterator ill-formed when three_way_comparable<W> is not satisfied.
We can either add an exposition-only safe-compare-three-way-result-t alias that denotes void or std::nonesuch for spaceship-less types, so the declaration is valid (and then disabled by the constraints), or simply make them return auto.[2020-02 Prioritized as IMMEDIATE Monday morning in Prague]
Proposed resolution:
This wording is relative to N4849.
Modify 26.6.4.3 [range.iota.iterator] as indicated:
namespace std::ranges { template<class W, class Bound> struct iota_view<W, Bound>::iterator { […] friend constexpr[…]compare_three_way_result_t<W>auto operator<=>( const iterator& x, const iterator& y) requires totally_ordered<W> && three_way_comparable<W>; […] }; […] }friend constexprcompare_three_way_result_t<W>auto operator<=>(const iterator& x, const iterator& y) requires totally_ordered<W> && three_way_comparable<W>;-19- Effects: Equivalent to: return x.value_ <=> y.value_;
Modify 26.7.9.3 [range.transform.iterator] as indicated:
namespace std::ranges { template<class V, class F> template<bool Const> class transform_view<V, F>::iterator { […] friend constexpr[…]compare_three_way_result_t<iterator_t<Base>>auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; […] }; […] }friend constexprcompare_three_way_result_t<iterator_t<Base>>auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;-19- Effects: Equivalent to: return x.current_ <=> y.current_;
Modify 26.7.22.3 [range.elements.iterator] as indicated:
namespace std::ranges { template<class V, size_t N> template<bool Const> class elements_view<V, N>::iterator { […] friend constexpr[…]compare_three_way_result_t<iterator_t<base-t>>auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<base-t> && three_way_comparable<iterator_t<base-t>>; […] }; […] }friend constexprcompare_three_way_result_t<iterator_t<base-t>>auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<base-t> && three_way_comparable<iterator_t<base-t>>;-18- Effects: Equivalent to: return x.current_ <=> y.current_;