Should be addressed after merging #2960, not before.
We're currently inconsistent about whether parallel algorithms use _REQUIRE_PARALLEL_ITERATOR (for reading) and _REQUIRE_CPP17_MUTABLE_ITERATOR (for writing).
The following overloads (found by searching for all occurrences of _ExPo&&) are missing enforcement. Some are just calling the classic serial algorithms, others are doing real parallel work:
<algorithm>:
swap_ranges(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _Dest)
generate(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Fn _Func)
unique(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)
unique(_ExPo&&, _FwdIt _First, _FwdIt _Last)
shift_left(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift)
shift_right(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift)
stable_partition(_ExPo&&, _BidIt _First, _BidIt _Last, _Pr _Pred)
inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last, _Pr _Pred)
inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last)
partial_sort(_ExPo&&, _RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred)
partial_sort(_ExPo&&, _RanIt _First, _RanIt _Mid, _RanIt _Last)
nth_element(_ExPo&&, _RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred)
nth_element(_ExPo&&, _RanIt _First, _RanIt _Nth, _RanIt _Last)
max_element(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)
max_element(_ExPo&&, _FwdIt _First, _FwdIt _Last)
min_element(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)
min_element(_ExPo&&, _FwdIt _First, _FwdIt _Last)
minmax_element(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)
minmax_element(_ExPo&&, _FwdIt _First, _FwdIt _Last)
<execution>:
adjacent_find(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)
search_n(_ExPo&&, const _FwdIt _First, _FwdIt _Last, const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred)
remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pred)
sort(_ExPo&&, const _RanIt _First, const _RanIt _Last, _Pr _Pred)
stable_sort(_ExPo&&, const _BidIt _First, const _BidIt _Last, _Pr _Pred)
partition(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pred)
<xutility>:
reverse(_ExPo&&, _BidIt _First, _BidIt _Last)
rotate(_ExPo&&, _FwdIt _First, _FwdIt _Mid, _FwdIt _Last)
Additionally (although less concerning), there are some _ExPo&& overloads that check the requirements and then call another _ExPo&& overload. This is inconsistently done (more often, it seems that we directly call another _ExPo&& overload and expect it to perform checking).
I think that a reasonable policy would be: all _ExPo&& overloads (of publicly usable functions) should immediately perform checking, whether they're calling classic serial or doing real work, unless they are immediately calling another _ExPo&& overload (typically to provide defaulted comparators etc).
Should be addressed after merging #2960, not before.
We're currently inconsistent about whether parallel algorithms use
_REQUIRE_PARALLEL_ITERATOR(for reading) and_REQUIRE_CPP17_MUTABLE_ITERATOR(for writing).The following overloads (found by searching for all occurrences of
_ExPo&&) are missing enforcement. Some are just calling the classic serial algorithms, others are doing real parallel work:<algorithm>:swap_ranges(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _Dest)generate(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Fn _Func)unique(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)unique(_ExPo&&, _FwdIt _First, _FwdIt _Last)shift_left(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift)shift_right(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _Pos_to_shift)stable_partition(_ExPo&&, _BidIt _First, _BidIt _Last, _Pr _Pred)inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last, _Pr _Pred)inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last)partial_sort(_ExPo&&, _RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred)partial_sort(_ExPo&&, _RanIt _First, _RanIt _Mid, _RanIt _Last)nth_element(_ExPo&&, _RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred)nth_element(_ExPo&&, _RanIt _First, _RanIt _Nth, _RanIt _Last)max_element(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)max_element(_ExPo&&, _FwdIt _First, _FwdIt _Last)min_element(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)min_element(_ExPo&&, _FwdIt _First, _FwdIt _Last)minmax_element(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)minmax_element(_ExPo&&, _FwdIt _First, _FwdIt _Last)<execution>:adjacent_find(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred)search_n(_ExPo&&, const _FwdIt _First, _FwdIt _Last, const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred)remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pred)sort(_ExPo&&, const _RanIt _First, const _RanIt _Last, _Pr _Pred)stable_sort(_ExPo&&, const _BidIt _First, const _BidIt _Last, _Pr _Pred)partition(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pred)<xutility>:reverse(_ExPo&&, _BidIt _First, _BidIt _Last)rotate(_ExPo&&, _FwdIt _First, _FwdIt _Mid, _FwdIt _Last)Additionally (although less concerning), there are some
_ExPo&&overloads that check the requirements and then call another_ExPo&&overload. This is inconsistently done (more often, it seems that we directly call another_ExPo&&overload and expect it to perform checking).I think that a reasonable policy would be: all
_ExPo&&overloads (of publicly usable functions) should immediately perform checking, whether they're calling classic serial or doing real work, unless they are immediately calling another_ExPo&&overload (typically to provide defaulted comparators etc).