Skip to content

<algorithm>, <xutility>: Usage of _Prefer_iterator_copies should inspect unwrapped iterators #4663

@StephanTLavavej

Description

@StephanTLavavej

Noticed while looking at #4660 but this is a distinct issue.

All of our uses of _Prefer_iterator_copies are inspecting iterator_t<_Rng>, which is the range's original iterator, but we're actually working with the unwrapped iterator type:

STL/stl/inc/algorithm

Lines 10417 to 10419 in 8dc4faa

if constexpr (forward_range<_Rng> && _Prefer_iterator_copies<iterator_t<_Rng>>) {
return _Minmax_fwd_unchecked(
_STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj));

STL/stl/inc/xutility

Lines 7018 to 7020 in 8dc4faa

if constexpr (forward_range<_Rng> && _Prefer_iterator_copies<iterator_t<_Rng>>) {
return static_cast<range_value_t<_Rng>>(*_RANGES _Max_element_unchecked(
_STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)));

STL/stl/inc/xutility

Lines 7236 to 7238 in 8dc4faa

if constexpr (forward_range<_Rng> && _Prefer_iterator_copies<iterator_t<_Rng>>) {
return static_cast<range_value_t<_Rng>>(*_RANGES _Min_element_unchecked(
_STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)));

_Prefer_iterator_copies cares about both size and trivially-copyable, so wrapped vs. unwrapped is a significant difference:

STL/stl/inc/xutility

Lines 6962 to 6966 in 8dc4faa

template <class _It>
concept _Prefer_iterator_copies = // When we have a choice, should we copy iterators or copy elements?
// pre: input_iterator<_It>
sizeof(_It) <= 2 * sizeof(iter_value_t<_It>)
&& (is_trivially_copyable_v<_It> || !is_trivially_copyable_v<iter_value_t<_It>>);

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixedSomething works now, yay!performanceMust go fasterrangesC++20/23 ranges

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions