concat_view::iterator::operator-
is overconstrainedSection: 25.7.18.3 [range.concat.iterator] Status: New Submitter: Hewill Kang Opened: 2024-04-26 Last modified: 2024-08-02
Priority: 3
View other active issues in [range.concat.iterator].
View all other issues in [range.concat.iterator].
View all issues with New status.
Discussion:
Currently, two concat_view::iterator
s can only be subtracted if
concat-is-random-access
is satisfied, which seems overconstrained since the implementation
does not rely on all underlying ranges being random_access_range
or common_range
.
operator-
mainly based on whether it satisfies
sized_sentinel_for
rather than being category-specific.
For example, counted_iterator
s that only model input_iterator
can still be subtracted.
We have no reason to reject the following:
std::list l = {1, 2, 3};
auto r = l | std::views::take(3);
auto c = std::ranges::concat_view{r};
auto it = c.begin();
it++;
auto d = it - c.begin(); // error: no match for 'operator-'
The proposed resolution lists a minimal constraint formula based on the implementation details of operator-
.
[2024-08-02; Reflector poll]
Set priority to 3 after reflector poll.
Proposed resolution:
This wording is relative to N4981.
Modify 25.7.18.3 [range.concat.iterator] as indicated:
[…]namespace std::ranges { template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && concatable<Views...> template<bool Const> class concat_view<Views...>::iterator { public: […] friend constexpr difference_type operator-(const iterator& x, const iterator& y) requiresconcat-is-random-access<Const, Views...>see below; […] }; }friend constexpr difference_type operator-(const iterator& x, const iterator& y) requiresconcat-is-random-access<Const, Views...>see below;-32- Preconditions:
x.it_.valueless_by_exception()
andy.it_.valueless_by_exception()
are eachfalse
.-33- Effects: Let
ix
denotex.it_.index()
andiy
denotey.it_.index()
.
(33.1) — if
ix > iy
, letdy
beranges::distance(std::get<iy>(y.it_), ranges::end(std::get<iy>(y.parent_->views_)))
,dx
beranges::distance(ranges::begin(std::get<ix>(x.parent_->views_)), std::get<ix>(x.it_))
. Lets
denote the sum of the sizes of all the rangesstd::get<i>(x.parent_->views_)
for every integeri
in the range[iy + 1, ix)
if there is any, and0
otherwise, of typedifference_type
, equivalent to:return dy + s + dx;(33.2) — otherwise, if
ix < iy
istrue
, equivalent to:return -(y - x);(33.3) — otherwise, equivalent to:
return std::get<ix>(x.it_) - std::get<iy>(y.it_);-?- Remarks: Let
Fs
be the pack that consists of all elements ofViews
except the last element, and letRs
be the pack that consists of all elements ofViews
except the first element. The expression in the requires-clause is equivalent to:(sized_sentinel_for<iterator_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...) && (sized_sentinel_for<sentinel_t<maybe-const<Const, Fs>>, iterator_t<maybe-const<Const, Fs>>> && ...) && all-forward<Const, Rs...>