base() const &
consistent across iterator wrappers that supports input_iterator
sSection: 25.7.8.3 [range.filter.iterator], 25.7.9.3 [range.transform.iterator], 25.7.23.3 [range.elements.iterator] Status: C++23 Submitter: Tomasz Kamiński Opened: 2021-03-14 Last modified: 2023-11-22
Priority: Not Prioritized
View all issues with C++23 status.
Discussion:
The resolution of LWG issue 3391 changed the base()
function for the
counted_iterator
/move_iterator
to return const &
, because the previous
specification prevented non-mutating uses of the base iterator (comparing against sentinel) and made
take_view
unimplementable. However, this change was not applied for all other iterators wrappers,
that may wrap move-only input iterators. As consequence, we end-up with inconsistency where a user can
perform the following operations on some adapters, but not on others (e. g. take_view
uses
counted_iterator
so it supports them).
read the original value of the base iterator, by calling operator*
find position of an element in the underlying iterator, when sentinel is sized by calling operator-
(e.g. all input iterators wrapped into counted_iterator
).
To fix above, the proposed wording below proposes to modify the signature of iterator::base() const &
member function for all iterators adapters that support input iterator. These include:
filter_view::iterator
(uses case B)
transform_view::iterator
(uses case A)
elements_view::iterator
(uses case B)
lazy_split_view<V, Pattern>::inner-iterator
(uses case B) if
P2210 is accepted
Note: common_iterator
does not expose the base()
function (because it can either point to
iterator or sentinel), so changes to above are not proposed. However, both (A) and (B) use cases are supported.
[2021-04-20; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
[2021-06-07 Approved at June 2021 virtual plenary. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4878.
If P2210 would become accepted, the corresponding subclause [range.lazy.split.inner] (?) for
lazy_split_view::inner-iterator
would require a similar change.
Modify 25.7.8.3 [range.filter.iterator] as indicated:
[…][…] constexpr const iterator_t<V>& base() const &requires copyable<iterator_t<V>>; […]
constexpr const iterator_t<V>& base() const &requires copyable<iterator_t<V>>;-5- Effects: Equivalent to:
return current_;
Modify 25.7.9.3 [range.transform.iterator] as indicated:
[…][…] constexpr const iterator_t<Base>& base() const &requires copyable<iterator_t<Base>>; […]
constexpr const iterator_t<Base>& base() const &requires copyable<iterator_t<Base>>;-5- Effects: Equivalent to:
return current_;
Modify 25.7.23.3 [range.elements.iterator] as indicated:
[…][…] constexpr const iterator_t<Base>& base() const &requires copyable<iterator_t<Base>>; […]
constexpr const iterator_t<Base>& base() const &requires copyable<iterator_t<Base>>;-3- Effects: Equivalent to:
return current_;