move_iterator
missing disable_sized_sentinel_for
specializationSection: 24.2 [iterator.synopsis] Status: C++23 Submitter: Hewill Kang Opened: 2022-07-14 Last modified: 2023-11-22
Priority: Not Prioritized
View all other issues in [iterator.synopsis].
View all issues with C++23 status.
Discussion:
Since reverse_iterator::operator-
is not constrained, the standard adds a
disable_sized_sentinel_for
specialization for it to avoid situations where the
underlying iterator can be subtracted making reverse_iterator
accidentally model
sized_sentinel_for
.
move_iterator::operator-
is also unconstrained and the standard
does not have the disable_sized_sentinel_for
specialization for it, this makes
subrange<move_iterator<I>, move_iterator<I>>
unexpectedly satisfy
sized_range
and incorrectly use I::operator-
to get size when I
can be subtracted but not modeled sized_sentinel_for<I>
.
In addition, since P2520 makes move_iterator
no longer just input_iterator
,
ranges::size
can get the size of the range by subtracting two move_iterator
pairs,
this also makes r | views::as_rvalue
may satisfy sized_range
when neither r
nor
r | views::reverse
is sized_range
.
We should add a move_iterator
version of the disable_sized_sentinel_for
specialization to the standard to avoid the above situation.
[2022-08-23; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
"but I don't think the issue text is quite right - both
move_iterator
and reverse_iterator
's
operator-
are constrained on x.base() - y.base()
being valid."
Does anyone remember why we did this for reverse_iterator
and not move_iterator
?
[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4910.
Modify 24.2 [iterator.synopsis], header <iterator>
synopsis, as indicated:
namespace std::ranges { […] template<class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i); template<class Iterator1, class Iterator2> requires (!sized_sentinel_for<Iterator1, Iterator2>) inline constexpr bool disable_sized_sentinel_for<move_iterator<Iterator1>, move_iterator<Iterator2>> = true; […] }