This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
3453. Generic code cannot callranges::advance(i, s)
Section: 24.4.4.2 [range.iter.op.advance], 24.3.4.7 [iterator.concept.sentinel] Status: C++23 Submitter: Casey Carter Opened: 2020-06-18 Last modified: 2023-11-22
Priority: 2
View all other issues in [range.iter.op.advance].
View all issues with C++23 status.
Discussion:
The specification of the iterator & sentinel overload of ranges::advance
in 24.4.4.2 [range.iter.op.advance] reads:
template<input_or_output_iterator I, sentinel_for<I> S> constexpr void ranges::advance(I& i, S bound);-3- Preconditions:
-4- Effects:[i, bound)
denotes a range.
(4.1) — If
I
andS
modelassignable_from<I&, S>
, equivalent toi = std::move(bound)
.(4.2) — […]
The assignment optimization in bullet 4.1 is just fine for callers with concrete types who can decide whether or not to call advance
depending on the semantics of the assignment performed. However, since this assignment operation isn't part of the input_or_output_iterator
or sentinel_for
requirements its semantics are unknown for arbitrary types. Effectively, generic code is forbidden to call this overload of advance
when assignable_from<I&, S>
is satisfied and non-generic code must tread lightly. This seems to make the library dangerously unusable. We can correct this problem by either:
Making the assignment operation in question an optional part of the sentinel_for
concept with well-defined semantics. This concept change should be relatively safe given that assignable_from<I&, S>
requires common_reference_with<const I&, const S&>
, which is very rarely satisfied inadvertently.
Requiring instead same_as<I, S>
to trigger the assignment optimization in bullet 4.1 above. S
is semiregular
, so i = std::move(s)
is certainly well-formed (and has well-defined semantics thanks to semiregular
) when I
and S
are the same type. The optimization will not apply in as many cases, but we don't need to make a scary concept change, either.
[2020-06-26; Reflector prioritization]
Set priority to 2 after reflector discussions.
[2020-08-21; Issue processing telecon: Option A is Tentatively Ready]
Previous resolution [SUPERSEDED]:
This wording is relative to N4861.
Wording for both Option A and Option B are provided.
Option A:
Modify 24.3.4.7 [iterator.concept.sentinel] as indicated:
template<class S, class I> concept sentinel_for = semiregular<S> && input_or_output_iterator<I> && weakly-equality-comparable-with<S, I>; // See 18.5.4 [concept.equalitycomparable]-2- Let
s
andi
be values of typeS
andI
such that[i, s)
denotes a range. TypesS
andI
modelsentinel_for<S, I>
only if
(2.1) —
i == s
is well-defined.(2.2) — If
bool(i != s)
theni
is dereferenceable and[++i, s)
denotes a range.(2.?) —
assignable_from<I&, S>
is either modeled or not satisfied.Option B:
Modify 24.4.4.2 [range.iter.op.advance] as indicated:
template<input_or_output_iterator I, sentinel_for<I> S> constexpr void ranges::advance(I& i, S bound);-3- Preconditions:
-4- Effects:[i, bound)
denotes a range.
(4.1) — If
I
andS
modelassignable_from<I&, S> same_as<I, S>
, equivalent toi = std::move(bound)
.(4.2) — […]
[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]
Proposed resolution:
This wording is relative to N4861.
Modify 24.3.4.7 [iterator.concept.sentinel] as indicated:
template<class S, class I> concept sentinel_for = semiregular<S> && input_or_output_iterator<I> && weakly-equality-comparable-with<S, I>; // See 18.5.4 [concept.equalitycomparable]-2- Let
s
andi
be values of typeS
andI
such that[i, s)
denotes a range. TypesS
andI
modelsentinel_for<S, I>
only if
(2.1) —
i == s
is well-defined.(2.2) — If
bool(i != s)
theni
is dereferenceable and[++i, s)
denotes a range.(2.?) —
assignable_from<I&, S>
is either modeled or not satisfied.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4