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;
[…]
}