-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<algorithm>
: Unwrapping output iterators in range algorithms
#893
Comments
Relabeling as |
Reviewing #983, I believe that |
Should we also audit for |
Yes, I've expanded the problem statement. |
<algorithm>
: Unwrapping output iterators in range algorithms
std
algorithms validate checked/wrapped iterators and unwrap them into unchecked/unwrapped iterators before operating on them. This lets us both help users find bugs in the arguments they pass to algorithms and have algorithms be performant even when given checked iterators. The pertinent machinery is:_Adl_verify_range(first, last)
tries to validate the range[first, last)
by calling a user customization point via argument dependent lookup._Get_unwrapped(x)
extracts an unwrapped iterator/sentinel from the wrapped iterator/sentinelx
._Get_unwrapped_unverified(x)
either returnsx
or extracts an unwrapped iterator fromx
(as determined by the author ofx
's type) whose range we cannot verify because we don't know a priori how many elements will be written._Idl_distance<I>(first, last)
returnsiter_difference_t<I>(last - first)
whenlast - first
is valid, and otherwise returns a value of the tag type_Distance_unknown
. (The idea here is that you pass the wrapped iterator typeI
and unwrapped iterator/sentinelfirst
andlast
, but I'm not sure we want to tolerate corresponding wrapped and unwrapped iterator types with differing difference types. Someone needs to ask @BillyONeal.)_Get_unwrapped_n(x, n)
has behavior that depends on the type ofn
:_Distance_unkown
,_Get_unwrapped_n
returns_Get_unwrapped_unverified(x)
.iter_difference_t<decltype(x)>
and_Get_unwrapped_n
both validates thatx + [0, n)
is a valid counted range and returns an unwrapped iterator extracted from the wrapped iteratorx
._Seek_wrapped(w, u)
injects unwrapped iteratoru
into the wrapped iteratorw
, both of which denote elements of the same range. This is used to compute return values.Currently all of the above work with Ranges move-only iterators and differing iterator/sentinel types except for
_Idl_distance
. Consequently the unwrapping story for output iterators passed to Ranges algorithms is very poor. We need aranges::_Idl_distance
which handles iterator/sentinel pairs and move-only iterators and knows aboutsized_sentinel_for
. We should also have a range overload of_Idl_distance
so we can simply write:Once
_Idl_distance
is squared away, we need to audit all range algorithms and add unwrapping/rewrapping support for output iterators. We've already_Get_unwrapped_unverified
for some (but not all) appropriate algorithms, the vast majority don't unwrap iterators and should therefore be easily found. It's probably also a good idea to have theoperator*
implementations intest::iterator
(defined intests/std/tests/range_algorithm_support.hpp
)static_assert
that the iterator type is unwrapped to both help with the algorithm audit and guard against future regressions.The text was updated successfully, but these errors were encountered: