view
iterator types have ill-formed <=>
operatorsSection: 25.6.4.3 [range.iota.iterator], 25.7.9.3 [range.transform.iterator], 25.7.23.3 [range.elements.iterator] Status: C++20 Submitter: Jonathan Wakely Opened: 2020-02-07 Last modified: 2021-02-25
Priority: 0
View other active issues in [range.iota.iterator].
View all other issues in [range.iota.iterator].
View all issues with C++20 status.
Discussion:
25.6.4.3 [range.iota.iterator] and 25.7.9.3 [range.transform.iterator] and
25.7.23.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.
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 25.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 25.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 25.7.23.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_;