diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 49158096e70..5753fae47c5 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -663,7 +663,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( auto _ULast1 = _Get_unwrapped(_Last1); auto _UFirst2 = _Get_unwrapped(_First2); const auto _ULast2 = _Get_unwrapped(_Last2); - if constexpr (_Is_random_iter_v<_InIt1> && _Is_random_iter_v<_InIt2>) { + if constexpr (_Is_ranges_random_iter_v<_InIt1> && _Is_ranges_random_iter_v<_InIt2>) { using _CT = _Common_diff_t<_InIt1, _InIt2>; const _CT _Count1 = _ULast1 - _UFirst1; const _CT _Count2 = _ULast2 - _UFirst2; @@ -853,7 +853,7 @@ _NODISCARD _CONSTEXPR20 bool is_permutation( auto _ULast1 = _Get_unwrapped(_Last1); auto _UFirst2 = _Get_unwrapped(_First2); auto _ULast2 = _Get_unwrapped(_Last2); - if constexpr (_Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2>) { + if constexpr (_Is_ranges_random_iter_v<_FwdIt1> && _Is_ranges_random_iter_v<_FwdIt2>) { if (_ULast1 - _UFirst1 != _ULast2 - _UFirst2) { return false; } @@ -866,7 +866,9 @@ _NODISCARD _CONSTEXPR20 bool is_permutation( } return true; - } else if constexpr (_Is_fwd_iter_v<_FwdIt1> && _Is_fwd_iter_v<_FwdIt2>) { + } else { + static_assert(_Is_ranges_fwd_iter_v<_FwdIt1> && _Is_ranges_fwd_iter_v<_FwdIt2>, + "Iterators must be at least forward iterators"); for (;; ++_UFirst1, (void) ++_UFirst2) { // trim matching prefix if (_UFirst1 == _ULast1) { return _UFirst2 == _ULast2; @@ -896,8 +898,6 @@ _NODISCARD _CONSTEXPR20 bool is_permutation( return false; // sequence 1 is longer than sequence 2, not a permutation } } - } else { - static_assert(_Always_false<_FwdIt1>, "Iterators must be at least forward iterators"); } } @@ -1449,7 +1449,7 @@ _FwdIt2 copy_if(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _Pr _Pred // copy each satisfying _Pred // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD copy_if(_First, _Last, _Dest, _Pass_fn(_Pred)); } #endif // _HAS_CXX17 @@ -1638,8 +1638,8 @@ pair<_FwdIt2, _FwdIt3> partition_copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _F // copy true partition to _Dest_true, false to _Dest_false // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD partition_copy(_First, _Last, _Dest_true, _Dest_false, _Pass_fn(_Pred)); } @@ -1947,7 +1947,7 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHays const auto _ULast1 = _Get_unwrapped(_Last1); const auto _UFirst2 = _Get_unwrapped(_First2); const auto _ULast2 = _Get_unwrapped(_Last2); - if constexpr (_Is_random_iter_v<_FwdItHaystack> && _Is_random_iter_v<_FwdItPat>) { + if constexpr (_Is_ranges_random_iter_v<_FwdItHaystack> && _Is_ranges_random_iter_v<_FwdItPat>) { const _Iter_diff_t<_FwdItPat> _Count2 = _ULast2 - _UFirst2; if (_ULast1 - _UFirst1 >= _Count2) { const auto _Last_possible = _ULast1 - static_cast<_Iter_diff_t<_FwdItHaystack>>(_Count2); @@ -2027,7 +2027,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt search_n( _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Is_random_iter_v<_FwdIt>) { + if constexpr (_Is_ranges_random_iter_v<_FwdIt>) { const auto _Count_diff = static_cast<_Iter_diff_t<_FwdIt>>(_Count); auto _UOld_first = _UFirst; for (_Iter_diff_t<_FwdIt> _Inc = 0; _Count_diff <= _ULast - _UOld_first;) { // enough room, look for a match @@ -2569,7 +2569,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( const auto _ULast1 = _Get_unwrapped(_Last1); const auto _UFirst2 = _Get_unwrapped(_First2); const auto _ULast2 = _Get_unwrapped(_Last2); - if constexpr (_Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2>) { + if constexpr (_Is_ranges_random_iter_v<_FwdIt1> && _Is_ranges_random_iter_v<_FwdIt2>) { const _Iter_diff_t<_FwdIt2> _Count2 = _ULast2 - _UFirst2; if (_Count2 > 0 && _Count2 <= _ULast1 - _UFirst1) { for (auto _UCandidate = _ULast1 - static_cast<_Iter_diff_t<_FwdIt1>>(_Count2);; --_UCandidate) { @@ -2585,7 +2585,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( } return _Last1; - } else if constexpr (_Is_bidi_iter_v<_FwdIt1> && _Is_bidi_iter_v<_FwdIt2>) { + } else if constexpr (_Is_ranges_bidi_iter_v<_FwdIt1> && _Is_ranges_bidi_iter_v<_FwdIt2>) { for (auto _UCandidate = _ULast1;; --_UCandidate) { // try a match at _UCandidate auto _UNext1 = _UCandidate; auto _UNext2 = _ULast2; @@ -3370,7 +3370,7 @@ _FwdIt2 replace_copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, cons // copy replacing each matching _Oldval with _Newval // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD replace_copy(_First, _Last, _Dest, _Oldval, _Newval); } #endif // _HAS_CXX17 @@ -3465,7 +3465,7 @@ _FwdIt2 replace_copy_if(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _ // copy replacing each satisfying _Pred with _Val // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD replace_copy_if(_First, _Last, _Dest, _Pass_fn(_Pred), _Val); } #endif // _HAS_CXX17 @@ -3683,7 +3683,7 @@ template -concept _Can_reread_dest = forward_iterator<_OutIt> && same_as, iter_value_t<_OutIt>>; -#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv template -_INLINE_VAR constexpr bool _Can_reread_dest = _Is_fwd_iter_v<_OutIt> // - && is_same_v<_Iter_value_t<_InIt>, _Iter_value_t<_OutIt>>; -#endif // __cpp_lib_concepts +#ifdef __cpp_lib_concepts +concept +#else +_INLINE_VAR constexpr bool +#endif + _Can_reread_dest = _Is_cpp17_fwd_iter_v<_OutIt> && is_same_v<_Iter_value_t<_InIt>, _Iter_value_t<_OutIt>>; template _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { @@ -4119,7 +4118,7 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr auto _UDest = _Get_unwrapped_unverified(_Dest); - if constexpr (_Is_fwd_iter_v<_InIt>) { // can reread the source for comparison + if constexpr (_Is_ranges_fwd_iter_v<_InIt>) { // can reread the source for comparison auto _Firstb = _UFirst; *_UDest = *_Firstb; @@ -4172,7 +4171,7 @@ _FwdIt2 unique_copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _Pr _ // copy compressing pairs that match // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD unique_copy(_First, _Last, _Dest, _Pass_fn(_Pred)); } @@ -4181,7 +4180,7 @@ _FwdIt2 unique_copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest) noexc // copy compressing pairs that match // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD unique_copy(_First, _Last, _Dest); } #endif // _HAS_CXX17 @@ -4408,7 +4407,8 @@ template _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Urng&& _Func) { // randomly select _Count elements from [_First, _Last) into _Dest - static_assert(_Is_fwd_iter_v<_PopIt> || _Is_random_iter_v<_SampleIt>, - "If the source range is not forward, the destination range must be random-access."); + static_assert(_Is_ranges_fwd_iter_v<_PopIt> || _Is_cpp17_random_iter_v<_SampleIt>, + "If the source range is not forward, the destination range must be a Cpp17RandomAccessIterator."); + static_assert(is_integral_v<_Diff>, "The sample size must have an integer type."); _Adl_verify_range(_First, _Last); if (0 < _Count) { @@ -4736,7 +4738,7 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Ur auto _ULast = _Get_unwrapped(_Last); using _PopDiff = _Iter_diff_t<_PopIt>; _Rng_from_urng<_PopDiff, remove_reference_t<_Urng>> _RngFunc(_Func); - if constexpr (_Is_fwd_iter_v<_PopIt>) { + if constexpr (_Is_ranges_fwd_iter_v<_PopIt>) { // source is forward: use selection sampling (stable) using _CT = common_type_t<_Diff, _PopDiff>; const auto _Pop_size = _STD distance(_UFirst, _ULast); @@ -4746,12 +4748,11 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count, _Ur _Seek_wrapped(_Dest, _Sample_selection_unchecked(_UFirst, _Pop_size, _Get_unwrapped_n(_Dest, _Count), _Count, _RngFunc)); - } else if constexpr (_Is_input_iter_v<_PopIt>) { + } else { + static_assert(_Is_ranges_input_iter_v<_PopIt>, "Source iterators must be at least input iterators"); // source is input: use reservoir sampling (unstable) _Seek_wrapped(_Dest, _Sample_reservoir_unchecked(_UFirst, _ULast, _Get_unwrapped_unverified(_Dest), _Count, _RngFunc)); - } else { - static_assert(_Always_false<_PopIt>, "Source iterators must be at least input iterators"); } } @@ -5010,7 +5011,7 @@ constexpr _FwdIt shift_left(_FwdIt _First, const _FwdIt _Last, _Iter_diff_t<_Fwd const auto _ULast = _Get_unwrapped(_Last); auto _Start_at = _UFirst; - if constexpr (_Is_random_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { if (_Pos_to_shift >= _ULast - _UFirst) { return _First; } @@ -5050,9 +5051,9 @@ constexpr _FwdIt shift_right(_FwdIt _First, const _FwdIt _Last, _Iter_diff_t<_Fw const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Is_bidi_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_bidi_iter_v<_FwdIt>) { auto _UEnd_at = _ULast; - if constexpr (_Is_random_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { if (_Pos_to_shift >= _ULast - _UFirst) { return _Last; } @@ -5353,7 +5354,7 @@ _CONSTEXPR20 _FwdIt partition(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Is_bidi_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_bidi_iter_v<_FwdIt>) { for (;;) { // find any out-of-order pair for (;;) { // skip in-place elements at beginning if (_UFirst == _ULast) { @@ -6770,7 +6771,7 @@ _FwdIt3 merge(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD merge(_First1, _Last1, _First2, _Last2, _Dest, _Pass_fn(_Pred)); } @@ -6781,7 +6782,7 @@ _FwdIt3 merge(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD merge(_First1, _Last1, _First2, _Last2, _Dest); } @@ -8470,6 +8471,7 @@ _RanIt partial_sort_copy(_ExPo&&, _FwdIt _First1, _FwdIt _Last1, _RanIt _First2, // copy [_First1, _Last1) into [_First2, _Last2) // parallelism suspected to be infeasible _REQUIRE_PARALLEL_ITERATOR(_FwdIt); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_RanIt); return _STD partial_sort_copy(_First1, _Last1, _First2, _Last2, _Pass_fn(_Pred)); } @@ -8479,6 +8481,7 @@ _RanIt partial_sort_copy(_ExPo&&, _FwdIt _First1, _FwdIt _Last1, _RanIt _First2, // copy [_First1, _Last1) into [_First2, _Last2) // parallelism suspected to be infeasible _REQUIRE_PARALLEL_ITERATOR(_FwdIt); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_RanIt); return _STD partial_sort_copy(_First1, _Last1, _First2, _Last2); } @@ -8868,7 +8871,7 @@ _FwdIt3 set_union(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Fw // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD set_union(_First1, _Last1, _First2, _Last2, _Dest, _Pass_fn(_Pred)); } @@ -8879,7 +8882,7 @@ _FwdIt3 set_union(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Fw // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD set_union(_First1, _Last1, _First2, _Last2, _Dest); } @@ -9266,7 +9269,7 @@ _FwdIt3 set_symmetric_difference(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdI // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD set_symmetric_difference(_First1, _Last1, _First2, _Last2, _Dest, _Pass_fn(_Pred)); } @@ -9277,7 +9280,7 @@ _FwdIt3 set_symmetric_difference(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdI // not parallelized at present, parallelism expected to be feasible in a future release _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); return _STD set_symmetric_difference(_First1, _Last1, _First2, _Last2, _Dest); } diff --git a/stl/inc/execution b/stl/inc/execution index f4e21e0a33b..1d8a318cd79 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -353,7 +353,7 @@ struct _Atomic_is_usually_lock_free : bool_constant::is_always_lock_ }; template -inline constexpr bool _Use_atomic_iterator = conjunction_v>, +inline constexpr bool _Use_atomic_iterator = conjunction_v>, is_trivially_copyable<_FwdIt>, _Atomic_is_usually_lock_free<_FwdIt>>; template @@ -823,7 +823,7 @@ struct _Iterator_range { // record of a partition of work _FwdIt _Last; }; -template , bool = _Is_random_iter_v<_FwdIt>> +template , bool = _Is_ranges_random_iter_v<_FwdIt>> struct _Static_partition_range; template @@ -943,7 +943,7 @@ struct _Static_partition_range<_FwdIt, _Diff, false> { } }; -template , bool = _Is_random_iter_v<_BidIt>> +template , bool = _Is_ranges_random_iter_v<_BidIt>> struct _Static_partition_range_backward; template @@ -1003,9 +1003,9 @@ struct _Static_partition_range_backward<_BidIt, _Diff, false> { template _Common_diff_t<_InIt1, _InIt2> _Distance_any(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { // get the distance from 2 ranges which should have identical lengths - if constexpr (_Is_random_iter_v<_InIt1>) { + if constexpr (_Is_ranges_random_iter_v<_InIt1>) { return _Last1 - _First1; - } else if constexpr (_Is_random_iter_v<_InIt2>) { + } else if constexpr (_Is_ranges_random_iter_v<_InIt2>) { return _Last2 - _First2; } else { return _STD distance(_First1, _Last1); @@ -1017,16 +1017,16 @@ _Common_diff_t<_InIt1, _InIt2> _Distance_min(_InIt1 _First1, const _InIt1 _Last1 // get min(distance(_First1, _Last1), distance(_First2, _Last2)) using _CT = _Common_diff_t<_InIt1, _InIt2>; _CT _Result{}; - if constexpr (_Is_random_iter_v<_InIt1> && _Is_random_iter_v<_InIt2>) { + if constexpr (_Is_ranges_random_iter_v<_InIt1> && _Is_ranges_random_iter_v<_InIt2>) { const _CT _Count1 = _Last1 - _First1; const _CT _Count2 = _Last2 - _First2; _Result = (_STD min)(_Count1, _Count2); - } else if constexpr (_Is_random_iter_v<_InIt1>) { + } else if constexpr (_Is_ranges_random_iter_v<_InIt1>) { for (auto _Count1 = _Last1 - _First1; 0 < _Count1 && _First2 != _Last2; --_Count1) { ++_First2; ++_Result; } - } else if constexpr (_Is_random_iter_v<_InIt2>) { + } else if constexpr (_Is_ranges_random_iter_v<_InIt2>) { for (auto _Count2 = _Last2 - _First2; 0 < _Count2 && _First1 != _Last1; --_Count2) { ++_First1; ++_Result; @@ -1189,7 +1189,7 @@ struct _Static_partitioned_for_each2 { // for_each task scheduled on the system template /* = 0 */> void for_each(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Fn _Func) noexcept /* terminates */ { // perform function for each element [_First, _Last) with the indicated execution policy - _REQUIRE_PARALLEL_ITERATOR(_FwdIt); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt); _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -1235,7 +1235,7 @@ _FwdIt _For_each_n_ivdep(_FwdIt _First, _Diff _Count, _Fn _Func) { template /* = 0 */> _FwdIt for_each_n(_ExPo&&, _FwdIt _First, const _Diff _Count_raw, _Fn _Func) noexcept /* terminates */ { // perform function for each element [_First, _First + _Count) - _REQUIRE_PARALLEL_ITERATOR(_FwdIt); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt); _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); @@ -1274,13 +1274,13 @@ using _Parallel_find_results = conditional_t<_Use_atomic_iterator<_FwdIt>, _Para _Parallel_choose_min_chunk<_FwdIt>>; template -struct _Static_partitioned_find2 { +struct _Static_partitioned_find3 { _Static_partition_team<_Iter_diff_t<_FwdIt>> _Team; _Static_partition_range<_FwdIt> _Basis; _Parallel_find_results<_FwdIt> _Results; _Find_fx _Fx; - _Static_partitioned_find2( + _Static_partitioned_find3( const size_t _Hw_threads, const _Iter_diff_t<_FwdIt> _Count, const _FwdIt _Last, const _Find_fx _Fx_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis{}, _Results(_Last), _Fx(_Fx_) {} @@ -1307,7 +1307,7 @@ struct _Static_partitioned_find2 { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_find2*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_find3*>(_Context)); } }; @@ -1320,7 +1320,7 @@ _FwdIt _Find_parallel_unchecked(_ExPo&&, const _FwdIt _First, const _FwdIt _Last const auto _Count = _STD distance(_First, _Last); if (_Count >= 2) { _TRY_BEGIN - _Static_partitioned_find2 _Operation{_Hw_threads, _Count, _Last, _Fx}; + _Static_partitioned_find3 _Operation{_Hw_threads, _Count, _Last, _Fx}; _Operation._Basis._Populate(_Operation._Team, _First); _Run_chunked_parallel_work(_Hw_threads, _Operation); return _Operation._Results._Get_result(); @@ -1396,7 +1396,7 @@ _Iter_diff_t<_FwdIt1> _Get_find_end_forward_partition_size( } template -struct _Static_partitioned_find_end_forward { +struct _Static_partitioned_find_end_forward2 { _Static_partition_team<_Iter_diff_t<_FwdIt1>> _Team; _Static_partition_range<_FwdIt1> _Basis; _Iterator_range<_FwdIt2> _Range2; @@ -1405,7 +1405,7 @@ struct _Static_partitioned_find_end_forward { _Parallel_choose_max_chunk<_FwdIt1>> _Results; - _Static_partitioned_find_end_forward(const size_t _Hw_threads, const _Iter_diff_t<_FwdIt1> _Count, + _Static_partitioned_find_end_forward2(const size_t _Hw_threads, const _Iter_diff_t<_FwdIt1> _Count, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2, const _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis{}, _Range2{_First2, _Last2}, _Pred{_Pred_}, _Results(_Last1) {} @@ -1434,7 +1434,7 @@ struct _Static_partitioned_find_end_forward { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - (void) static_cast<_Static_partitioned_find_end_forward*>(_Context)->_Process_chunk(); + (void) static_cast<_Static_partitioned_find_end_forward2*>(_Context)->_Process_chunk(); } }; @@ -1442,7 +1442,7 @@ template _BidIt1 _Get_find_end_backward_partition_start( const _BidIt1 _First1, _BidIt1 _Last1, _FwdIt2 _First2, const _FwdIt2 _Last2) { // gets the end of the range of possible matches for a find_end operation - if constexpr (_Is_random_iter_v<_BidIt1> && _Is_random_iter_v<_FwdIt2>) { + if constexpr (_Is_ranges_random_iter_v<_BidIt1> && _Is_ranges_random_iter_v<_FwdIt2>) { using _CT = _Common_diff_t<_BidIt1, _FwdIt2>; const _CT _Count1 = _Last1 - _First1; const _CT _Count2 = _Last2 - _First2; @@ -1472,7 +1472,7 @@ _BidIt1 _Get_find_end_backward_partition_start( } template -struct _Static_partitioned_find_end_backward2 { +struct _Static_partitioned_find_end_backward3 { _Static_partition_team<_Iter_diff_t<_BidIt1>> _Team; _Static_partition_range_backward<_BidIt1> _Basis; conditional_t<_Use_atomic_iterator<_BidIt1>, _Parallel_choose_max_result<_BidIt1>, @@ -1481,7 +1481,7 @@ struct _Static_partitioned_find_end_backward2 { _Iterator_range<_FwdIt2> _Range2; _Pr _Pred; - _Static_partitioned_find_end_backward2(const size_t _Hw_threads, const _Iter_diff_t<_BidIt1> _Count, + _Static_partitioned_find_end_backward3(const size_t _Hw_threads, const _Iter_diff_t<_BidIt1> _Count, const _BidIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2, const _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis{}, _Results(_Last1), _Range2{_First2, _Last2}, _Pred{_Pred_} {} @@ -1512,7 +1512,7 @@ struct _Static_partitioned_find_end_backward2 { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_find_end_backward2*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_find_end_backward3*>(_Context)); } }; @@ -1520,6 +1520,8 @@ template ::_Parallelize) { const size_t _Hw_threads = __std_parallel_algorithms_hw_threads(); if (_Hw_threads > 1) { - if constexpr (_Is_bidi_iter_v<_FwdIt1>) { + if constexpr (_Is_ranges_bidi_iter_v<_FwdIt1>) { const auto _Partition_start = _Get_find_end_backward_partition_start(_UFirst1, _ULast1, _UFirst2, _ULast2); if (_UFirst1 == _Partition_start) { @@ -1540,7 +1542,7 @@ _NODISCARD _FwdIt1 find_end(_ExPo&&, _FwdIt1 _First1, const _FwdIt1 _Last1, cons const auto _Count = _STD distance(_UFirst1, _Partition_start); if (_Count >= 2) { _TRY_BEGIN - _Static_partitioned_find_end_backward2 _Operation{ + _Static_partitioned_find_end_backward3 _Operation{ _Hw_threads, _Count, _ULast1, _UFirst2, _ULast2, _Pass_fn(_Pred)}; _Operation._Basis._Populate(_Operation._Team, _Partition_start); _Run_chunked_parallel_work(_Hw_threads, _Operation); @@ -1554,7 +1556,7 @@ _NODISCARD _FwdIt1 find_end(_ExPo&&, _FwdIt1 _First1, const _FwdIt1 _Last1, cons const auto _Count = _Get_find_end_forward_partition_size(_UFirst1, _ULast1, _UFirst2, _ULast2); if (_Count >= 2) { _TRY_BEGIN - _Static_partitioned_find_end_forward _Operation{ + _Static_partitioned_find_end_forward2 _Operation{ _Hw_threads, _Count, _ULast1, _UFirst2, _ULast2, _Pass_fn(_Pred)}; _Operation._Basis._Populate(_Operation._Team, _UFirst1); _Run_chunked_parallel_work(_Hw_threads, _Operation); @@ -1577,6 +1579,7 @@ _NODISCARD _FwdIt1 find_first_of(_ExPo&& _Exec, const _FwdIt1 _First1, _FwdIt1 _ const _FwdIt2 _Last2, _Pr _Pred) noexcept /* terminates */ { // look for one of [_First2, _Last2) that matches element _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); + _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); using _UFwdIt1 = _Unwrapped_t; _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -1595,13 +1598,13 @@ _NODISCARD _FwdIt1 find_first_of(_ExPo&& _Exec, const _FwdIt1 _First1, _FwdIt1 _ } template -struct _Static_partitioned_adjacent_find2 { +struct _Static_partitioned_adjacent_find3 { _Static_partition_team<_Iter_diff_t<_FwdIt>> _Team; _Static_partition_range<_FwdIt> _Basis; _Parallel_find_results<_FwdIt> _Results; _Pr _Pred; - _Static_partitioned_adjacent_find2( + _Static_partitioned_adjacent_find3( const size_t _Hw_threads, const _Iter_diff_t<_FwdIt> _Count, const _FwdIt _Last, const _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis{}, _Results{_Last}, _Pred{_Pred_} {} @@ -1634,7 +1637,7 @@ struct _Static_partitioned_adjacent_find2 { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_adjacent_find2*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_adjacent_find3*>(_Context)); } }; @@ -1650,7 +1653,7 @@ _NODISCARD _FwdIt adjacent_find(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred) const auto _Count = static_cast<_Iter_diff_t<_FwdIt>>(_STD distance(_UFirst, _ULast) - 1); if (_Count >= 2) { _TRY_BEGIN - _Static_partitioned_adjacent_find2 _Operation{_Hw_threads, _Count, _ULast, _Pass_fn(_Pred)}; + _Static_partitioned_adjacent_find3 _Operation{_Hw_threads, _Count, _ULast, _Pass_fn(_Pred)}; _Operation._Basis._Populate(_Operation._Team, _UFirst); _Run_chunked_parallel_work(_Hw_threads, _Operation); _Seek_wrapped(_Last, _Operation._Results._Get_result()); @@ -1742,8 +1745,8 @@ _NODISCARD _Iter_diff_t<_FwdIt> count(_ExPo&& _Exec, const _FwdIt _First, const } template >&& _Is_random_iter_v<_FwdIt2>, - bool = _Use_atomic_iterator<_Unwrapped_t>&& _Is_random_iter_v<_FwdIt1>> + bool = _Use_atomic_iterator<_Unwrapped_t>&& _Is_ranges_random_iter_v<_FwdIt2>, + bool = _Use_atomic_iterator<_Unwrapped_t>&& _Is_ranges_random_iter_v<_FwdIt1>> struct _Static_partitioned_mismatch_results; template @@ -1804,7 +1807,7 @@ struct _Static_partitioned_mismatch_results<_FwdIt1, _FwdIt2, false, false> { }; template -struct _Static_partitioned_mismatch2 { +struct _Static_partitioned_mismatch3 { using _Diff = _Common_diff_t<_FwdIt1, _FwdIt2>; _Static_partition_team<_Diff> _Team; _Static_partition_range<_FwdIt1, _Diff> _Basis1; @@ -1812,7 +1815,7 @@ struct _Static_partitioned_mismatch2 { _Static_partitioned_mismatch_results<_FwdIt1, _FwdIt2> _Results; _Pr _Pred; - _Static_partitioned_mismatch2( + _Static_partitioned_mismatch3( const size_t _Hw_threads, const _Diff _Count, const _FwdIt1 _First1, const _FwdIt2 _First2, const _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis1{}, _Basis2{}, _Results( @@ -1851,7 +1854,7 @@ struct _Static_partitioned_mismatch2 { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_mismatch2*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_mismatch3*>(_Context)); } }; @@ -1874,7 +1877,7 @@ _NODISCARD pair<_FwdIt1, _FwdIt2> mismatch( const auto _UFirst2 = _Get_unwrapped_n(_First2, _Count); if (_Count >= 2) { _TRY_BEGIN - _Static_partitioned_mismatch2 _Operation{_Hw_threads, _Count, _UFirst1, _UFirst2, _Pass_fn(_Pred)}; + _Static_partitioned_mismatch3 _Operation{_Hw_threads, _Count, _UFirst1, _UFirst2, _Pass_fn(_Pred)}; _Run_chunked_parallel_work(_Hw_threads, _Operation); const auto _Result = _Operation._Results._Get_result(_UFirst1, _UFirst2); _Seek_wrapped(_First2, _Result.second); @@ -1918,7 +1921,7 @@ _NODISCARD pair<_FwdIt1, _FwdIt2> mismatch( const auto _Count = static_cast<_Iter_diff_t<_FwdIt1>>(_Distance_min(_UFirst1, _ULast1, _UFirst2, _ULast2)); if (_Count >= 2) { _TRY_BEGIN - _Static_partitioned_mismatch2 _Operation{_Hw_threads, _Count, _UFirst1, _UFirst2, _Pass_fn(_Pred)}; + _Static_partitioned_mismatch3 _Operation{_Hw_threads, _Count, _UFirst1, _UFirst2, _Pass_fn(_Pred)}; _Run_chunked_parallel_work(_Hw_threads, _Operation); const auto _Result = _Operation._Results._Get_result(_UFirst1, _UFirst2); _Seek_wrapped(_First2, _Result.second); @@ -2052,7 +2055,7 @@ _NODISCARD bool equal(_ExPo&&, const _FwdIt1 _First1, const _FwdIt1 _Last1, cons } template -struct _Static_partitioned_search2 { +struct _Static_partitioned_search3 { _Static_partition_team<_Iter_diff_t<_FwdItHaystack>> _Team; _Static_partition_range<_FwdItHaystack> _Basis; _Parallel_find_results<_FwdItHaystack> _Results; @@ -2060,7 +2063,7 @@ struct _Static_partitioned_search2 { _FwdItPat _Last2; _Pr _Pred; - _Static_partitioned_search2(const size_t _Hw_threads, const _Iter_diff_t<_FwdItHaystack> _Count, + _Static_partitioned_search3(const size_t _Hw_threads, const _Iter_diff_t<_FwdItHaystack> _Count, const _FwdItHaystack _First1, const _FwdItHaystack _Last1, const _FwdItPat _First2_, const _FwdItPat _Last2_, _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis{}, _Results(_Last1), @@ -2092,7 +2095,7 @@ struct _Static_partitioned_search2 { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_search2*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_search3*>(_Context)); } }; @@ -2100,6 +2103,8 @@ template 1) { _Iter_diff_t<_FwdItHaystack> _Count; - if constexpr (_Is_random_iter_v<_FwdItHaystack> && _Is_random_iter_v<_FwdItPat>) { + if constexpr (_Is_ranges_random_iter_v<_FwdItHaystack> && _Is_ranges_random_iter_v<_FwdItPat>) { const auto _HaystackDist = _ULast1 - _UFirst1; const auto _NeedleDist = _ULast2 - _UFirst2; if (_NeedleDist > _HaystackDist) { // needle is longer than haystack, no match possible @@ -2155,7 +2160,7 @@ _NODISCARD _FwdItHaystack search(_ExPo&&, const _FwdItHaystack _First1, _FwdItHa } _TRY_BEGIN - _Static_partitioned_search2 _Operation{ + _Static_partitioned_search3 _Operation{ _Hw_threads, _Count, _UFirst1, _ULast1, _UFirst2, _ULast2, _Pass_fn(_Pred)}; _Run_chunked_parallel_work(_Hw_threads, _Operation); _Seek_wrapped(_Last1, _Operation._Results._Get_result()); @@ -2171,7 +2176,7 @@ _NODISCARD _FwdItHaystack search(_ExPo&&, const _FwdItHaystack _First1, _FwdItHa } template -struct _Static_partitioned_search_n2 { +struct _Static_partitioned_search_n3 { _Static_partition_team<_Iter_diff_t<_FwdIt>> _Team; _Static_partition_range<_FwdIt> _Basis; _Parallel_find_results<_FwdIt> _Results; @@ -2179,7 +2184,7 @@ struct _Static_partitioned_search_n2 { const _Ty& _Val; _Pr _Pred; - _Static_partitioned_search_n2(const size_t _Hw_threads, const _Iter_diff_t<_FwdIt> _Candidates, const _FwdIt _First, + _Static_partitioned_search_n3(const size_t _Hw_threads, const _Iter_diff_t<_FwdIt> _Candidates, const _FwdIt _First, const _FwdIt _Last, const _Iter_diff_t<_FwdIt> _Target_count_, const _Ty& _Val_, _Pr _Pred_) : _Team{_Candidates, _Get_chunked_work_chunk_count(_Hw_threads, _Candidates)}, _Basis{}, _Results(_Last), _Target_count(_Target_count_), _Val(_Val_), _Pred(_Pred_) { @@ -2219,7 +2224,7 @@ struct _Static_partitioned_search_n2 { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_search_n2*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_search_n3*>(_Context)); } }; @@ -2252,7 +2257,7 @@ _NODISCARD _FwdIt search_n(_ExPo&&, const _FwdIt _First, _FwdIt _Last, const _Di // +1 can't overflow because _Count > 0 const auto _Candidates = static_cast<_Iter_diff_t<_FwdIt>>(_Haystack_count - _Count + 1); _TRY_BEGIN - _Static_partitioned_search_n2 _Operation{_Hw_threads, _Candidates, _UFirst, _ULast, + _Static_partitioned_search_n3 _Operation{_Hw_threads, _Candidates, _UFirst, _ULast, static_cast<_Iter_diff_t<_FwdIt>>(_Count), _Val, _Pass_fn(_Pred)}; _Run_chunked_parallel_work(_Hw_threads, _Operation); _Seek_wrapped(_Last, _Operation._Results._Get_result()); @@ -2304,7 +2309,7 @@ _FwdIt2 transform(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _Last, _FwdIt2 _D /* terminates */ { // transform [_First, _Last) with _Func _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -2384,7 +2389,7 @@ _FwdIt3 transform(_ExPo&&, const _FwdIt1 _First1, const _FwdIt1 _Last1, const _F // transform [_First1, _Last1) and [_First2, ...) with _Func _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); _Adl_verify_range(_First1, _Last1); const auto _UFirst1 = _Get_unwrapped(_First1); const auto _ULast1 = _Get_unwrapped(_Last1); @@ -2427,7 +2432,7 @@ template (_Exec), _First, _Last, [&](auto&& _Value) { if (_STD forward(_Value) == _Oldval) { _STD forward(_Value) = _Newval; @@ -2439,7 +2444,7 @@ template (_Exec), _First, _Last, [&_Val, _Lambda_pred = _Pass_fn(_Pred)](auto&& _Value) mutable { if (_Lambda_pred(_STD forward(_Value))) { @@ -2996,14 +3001,14 @@ void stable_sort(_ExPo&&, const _BidIt _First, const _BidIt _Last, _Pr _Pred) no } template -struct _Static_partitioned_is_sorted_until { +struct _Static_partitioned_is_sorted_until2 { _Static_partition_team<_Iter_diff_t<_FwdIt>> _Team; // note offset partitioning: _Static_partition_range<_FwdIt> _Basis; // contains partition of [_First, _Last - 1) _Pr _Pred; _Parallel_find_results<_FwdIt> _Results; - _Static_partitioned_is_sorted_until( + _Static_partitioned_is_sorted_until2( _FwdIt _First, _FwdIt _Last, const size_t _Hw_threads, const _Iter_diff_t<_FwdIt> _Count, _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Basis{}, _Pred(_Pred_), _Results(_Last) { _Basis._Populate(_Team, _First); @@ -3037,7 +3042,7 @@ struct _Static_partitioned_is_sorted_until { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_is_sorted_until*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_is_sorted_until2*>(_Context)); } }; @@ -3055,7 +3060,7 @@ _NODISCARD _FwdIt is_sorted_until(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pre if (_Count >= 3) { // ... with at least 3 elements _TRY_BEGIN --_Count; // note unusual offset partitioning - _Static_partitioned_is_sorted_until _Operation{_UFirst, _ULast, _Hw_threads, _Count, _Pass_fn(_Pred)}; + _Static_partitioned_is_sorted_until2 _Operation{_UFirst, _ULast, _Hw_threads, _Count, _Pass_fn(_Pred)}; _Run_chunked_parallel_work(_Hw_threads, _Operation); _Seek_wrapped(_First, _Operation._Results._Get_result()); return _First; @@ -3223,14 +3228,14 @@ _NODISCARD bool is_partitioned(_ExPo&&, const _FwdIt _First, const _FwdIt _Last, } template -struct _Static_partitioned_is_heap_until { +struct _Static_partitioned_is_heap_until2 { using _Diff = _Iter_diff_t<_RanIt>; _Static_partition_team<_Diff> _Team; _RanIt _Range_first; _Pr _Pred; _Parallel_find_results<_RanIt> _Results; - _Static_partitioned_is_heap_until( + _Static_partitioned_is_heap_until2( _RanIt _First, _RanIt _Last, const size_t _Hw_threads, const _Diff _Count, _Pr _Pred_) : _Team{_Count, _Get_chunked_work_chunk_count(_Hw_threads, _Count)}, _Range_first(_First), _Pred(_Pred_), _Results(_Last) {} @@ -3263,7 +3268,7 @@ struct _Static_partitioned_is_heap_until { static void __stdcall _Threadpool_callback( __std_PTP_CALLBACK_INSTANCE, void* const _Context, __std_PTP_WORK) noexcept /* terminates */ { - _Run_available_chunked_work(*static_cast<_Static_partitioned_is_heap_until*>(_Context)); + _Run_available_chunked_work(*static_cast<_Static_partitioned_is_heap_until2*>(_Context)); } }; @@ -3280,7 +3285,7 @@ _NODISCARD _RanIt is_heap_until(_ExPo&&, _RanIt _First, _RanIt _Last, _Pr _Pred) const auto _Count = _ULast - _UFirst; if (_Count >= 3) { // ... with at least 3 elements _TRY_BEGIN - _Static_partitioned_is_heap_until _Operation{_UFirst, _ULast, _Hw_threads, _Count, _Pass_fn(_Pred)}; + _Static_partitioned_is_heap_until2 _Operation{_UFirst, _ULast, _Hw_threads, _Count, _Pass_fn(_Pred)}; _Run_chunked_parallel_work(_Hw_threads, _Operation); _Seek_wrapped(_First, _Operation._Results._Get_result()); return _First; @@ -3298,10 +3303,10 @@ _NODISCARD _RanIt is_heap_until(_ExPo&&, _RanIt _First, _RanIt _Last, _Pr _Pred) template pair<_FwdIt, _Iter_diff_t<_FwdIt>> _Partition_with_count_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // move elements satisfying _Pred to front and track how many elements satisfy _Pred - if constexpr (_Is_random_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { auto _Mid = _STD partition(_First, _Last, _Pred); return {_Mid, _Mid - _First}; - } else if constexpr (_Is_bidi_iter_v<_FwdIt>) { + } else if constexpr (_Is_cpp17_bidi_iter_v<_FwdIt>) { _Iter_diff_t<_FwdIt> _Trues{}; for (;;) { // find any out-of-order pair for (;;) { // skip in-place elements at beginning @@ -3361,7 +3366,7 @@ pair<_FwdIt, _Iter_diff_t<_FwdIt>> _Partition_swap_backward( // Swap elements in [_First, _Last) satisfying _Pred with elements from _Beginning_of_falses. // Pre: _Beginning_of_falses < _First _Iter_diff_t<_FwdIt> _Trues{}; - if constexpr (_Is_bidi_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_bidi_iter_v<_FwdIt>) { while (_First != _Last) { --_Last; if (_Pred(*_Last)) { @@ -3395,9 +3400,9 @@ _FwdIt _Partition_merge(const _FwdIt _False_first, const _FwdIt _True_first, con if (_Count1 < _Count2) { // move the false range to the end of the true range const _Iter_diff_t<_FwdIt> _Offset = _Count2 - _Count1; auto _Result = _True_first; - if constexpr (_Is_random_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { _Result += _Offset; - } else if constexpr (_Is_bidi_iter_v<_FwdIt>) { + } else if constexpr (_Is_cpp17_bidi_iter_v<_FwdIt>) { if (_Count1 < _Offset) { _Result = _True_last; _STD advance(_Result, -_Count1); @@ -3852,7 +3857,7 @@ _FwdIt3 set_intersection(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _Firs // AND sets [_First1, _Last1) and [_First2, _Last2) _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); auto _UFirst1 = _Get_unwrapped(_First1); @@ -3861,8 +3866,10 @@ _FwdIt3 set_intersection(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _Firs const auto _ULast2 = _Get_unwrapped(_Last2); auto _UDest = _Get_unwrapped_unverified(_Dest); using _Diff = _Common_diff_t<_FwdIt1, _FwdIt2, _FwdIt3>; - if constexpr (remove_reference_t<_ExPo>::_Parallelize - && _Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2> && _Is_random_iter_v<_FwdIt3>) { + if constexpr (remove_reference_t<_ExPo>::_Parallelize // + && _Is_ranges_random_iter_v<_FwdIt1> // + && _Is_ranges_random_iter_v<_FwdIt2> // + && _Is_cpp17_random_iter_v<_FwdIt3>) { // only parallelize if desired, and all of the iterators given are random access const size_t _Hw_threads = __std_parallel_algorithms_hw_threads(); if (_Hw_threads > 1) { // parallelize on multiprocessor machines @@ -3942,7 +3949,7 @@ _FwdIt3 set_difference(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2 // take set [_First2, _Last2) from [_First1, _Last1) _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt3); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt3); _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); auto _UFirst1 = _Get_unwrapped(_First1); @@ -3951,8 +3958,10 @@ _FwdIt3 set_difference(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2 const auto _ULast2 = _Get_unwrapped(_Last2); auto _UDest = _Get_unwrapped_unverified(_Dest); using _Diff = _Common_diff_t<_FwdIt1, _FwdIt2, _FwdIt3>; - if constexpr (remove_reference_t<_ExPo>::_Parallelize - && _Is_random_iter_v<_FwdIt1> && _Is_random_iter_v<_FwdIt2> && _Is_random_iter_v<_FwdIt3>) { + if constexpr (remove_reference_t<_ExPo>::_Parallelize // + && _Is_ranges_random_iter_v<_FwdIt1> // + && _Is_ranges_random_iter_v<_FwdIt2> // + && _Is_cpp17_random_iter_v<_FwdIt3>) { // only parallelize if desired, and all of the iterators given are random access const size_t _Hw_threads = __std_parallel_algorithms_hw_threads(); if (_Hw_threads > 1) { // parallelize on multiprocessor machines @@ -4389,7 +4398,7 @@ _FwdIt2 exclusive_scan(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _Last, _FwdI _BinOp _Reduce_op) noexcept /* terminates */ { // set each value in [_Dest, _Dest + (_Last - _First)) to the associative reduction of predecessors and _Val _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4518,7 +4527,7 @@ _FwdIt2 inclusive_scan(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _B /* terminates */ { // compute partial noncommutative and associative reductions including _Val into _Dest, using _Reduce_op _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4561,7 +4570,7 @@ _FwdIt2 inclusive_scan(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _B /* terminates */ { // compute partial noncommutative and associative reductions into _Dest, using _Reduce_op _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4705,7 +4714,7 @@ _FwdIt2 transform_exclusive_scan(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _L _BinOp _Reduce_op, _UnaryOp _Transform_op) noexcept /* terminates */ { // set each value in [_Dest, _Dest + (_Last - _First)) to the associative reduction of transformed predecessors _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4836,7 +4845,7 @@ _FwdIt2 transform_inclusive_scan(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _L _UnaryOp _Transform_op, _Ty _Val) noexcept /* terminates */ { // compute partial noncommutative and associative transformed reductions including _Val into _Dest _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4882,7 +4891,7 @@ _FwdIt2 transform_inclusive_scan(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _L _UnaryOp _Transform_op) noexcept /* terminates */ { // compute partial noncommutative and associative transformed reductions into _Dest _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4983,7 +4992,7 @@ _FwdIt2 adjacent_difference(_ExPo&&, const _FwdIt1 _First, const _FwdIt1 _Last, /* terminates */ { // compute adjacent differences into _Dest _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); diff --git a/stl/inc/functional b/stl/inc/functional index 46fb311a28f..01fe1fb5bbd 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -2186,7 +2186,7 @@ template _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( _FwdItHaystack _First1, _FwdItHaystack _Last1, _FwdItPat _First2, _FwdItPat _Last2, _Pred_eq& _Eq) { // find first [_First2, _Last2) satisfying _Eq - if constexpr (_Is_random_iter_v<_FwdItHaystack> && _Is_random_iter_v<_FwdItPat>) { + if constexpr (_Is_ranges_random_iter_v<_FwdItHaystack> && _Is_ranges_random_iter_v<_FwdItPat>) { _Iter_diff_t<_FwdItHaystack> _Count1 = _Last1 - _First1; _Iter_diff_t<_FwdItPat> _Count2 = _Last2 - _First2; @@ -2204,7 +2204,9 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( } return {_Last1, _Last1}; - } else if constexpr (_Is_fwd_iter_v<_FwdItHaystack> && _Is_fwd_iter_v<_FwdItPat>) { + } else { + static_assert(_Is_ranges_fwd_iter_v<_FwdItHaystack> && _Is_ranges_fwd_iter_v<_FwdItPat>, + "Iterators must be at least forward iterators"); for (;; ++_First1) { // loop until match or end of a sequence _FwdItHaystack _Mid1 = _First1; for (_FwdItPat _Mid2 = _First2;; ++_Mid1, (void) ++_Mid2) { @@ -2221,8 +2223,6 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( } } } - } else { - static_assert(_Always_false<_FwdItHaystack>, "Iterators must be at least forward iterators"); } } diff --git a/stl/inc/regex b/stl/inc/regex index 498bf80c3aa..47094a27966 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -1985,7 +1985,7 @@ private: template void _Reset(_InIt _First, _InIt _Last, flag_type _Flags) { // build regular expression from iterator range - if constexpr (_Is_fwd_iter_v<_InIt>) { + if constexpr (_Is_ranges_fwd_iter_v<_InIt>) { #if _ENHANCED_REGEX_VISUALIZER _Visualization.assign(_First, _Last); #endif // _ENHANCED_REGEX_VISUALIZER @@ -1994,7 +1994,7 @@ private: _Root_node* _Rx = _Prs._Compile(); _Reset(_Rx); } else { - static_assert(_Is_input_iter_v<_InIt>, "Iterators must be at least input iterators"); + static_assert(_Is_ranges_input_iter_v<_InIt>, "Iterators must be at least input iterators"); basic_string<_Iter_value_t<_InIt>> _Str(_First, _Last); diff --git a/stl/inc/vector b/stl/inc/vector index 18977a33583..6336018278c 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -694,7 +694,7 @@ public: _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Is_fwd_iter_v<_Iter>) { + if constexpr (_Is_ranges_fwd_iter_v<_Iter>) { const auto _Count = _Convert_size(static_cast(_STD distance(_UFirst, _ULast))); _Construct_n(_Count, _STD move(_UFirst), _STD move(_ULast)); #ifdef __cpp_lib_concepts @@ -1206,12 +1206,7 @@ public: _Adl_verify_range(_First, _Last); const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); -#ifdef __cpp_lib_concepts - constexpr bool _Is_fwd = _Is_fwd_iter_v<_Iter> || forward_iterator<_Iter>; -#else // ^^^ __cpp_lib_concepts ^^^ / vvv !__cpp_lib_concepts vvv - constexpr bool _Is_fwd = _Is_fwd_iter_v<_Iter>; -#endif // ^^^ !__cpp_lib_concepts ^^^ - if constexpr (_Is_fwd) { + if constexpr (_Is_ranges_fwd_iter_v<_Iter>) { _Insert_forward_range(_Where, _Get_unwrapped(_First), _Get_unwrapped(_Last)); } else { _Insert_input_range(_Where, _Get_unwrapped(_First), _Get_unwrapped(_Last)); @@ -1362,12 +1357,7 @@ public: template , int> = 0> _CONSTEXPR20 void assign(_Iter _First, _Iter _Last) { _Adl_verify_range(_First, _Last); -#ifdef __cpp_lib_concepts - constexpr bool _Is_fwd = _Is_fwd_iter_v<_Iter> || forward_iterator<_Iter>; -#else // ^^^ __cpp_lib_concepts ^^^ / vvv !__cpp_lib_concepts vvv - constexpr bool _Is_fwd = _Is_fwd_iter_v<_Iter>; -#endif // ^^^ !__cpp_lib_concepts ^^^ - if constexpr (_Is_fwd) { + if constexpr (_Is_ranges_fwd_iter_v<_Iter>) { _Assign_forward_range(_Get_unwrapped(_First), _Get_unwrapped(_Last)); } else { _Assign_input_range(_Get_unwrapped(_First), _Get_unwrapped(_Last)); @@ -3145,7 +3135,7 @@ public: _CONSTEXPR20 iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { const difference_type _Saved_offset = _Where - begin(); - if constexpr (_Is_fwd_iter_v<_Iter>) { + if constexpr (_Is_ranges_fwd_iter_v<_Iter>) { _Adl_verify_range(_First, _Last); const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); const size_type _Off = _Insert_x(_Where, _Count); diff --git a/stl/inc/xstring b/stl/inc/xstring index 93800fa01b1..201fa7eed12 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -2754,7 +2754,7 @@ private: _My_data._Mysize = 0; _My_data._Myres = _BUF_SIZE - 1; - if constexpr (_Is_fwd_iter_v<_Iter>) { + if constexpr (_Is_ranges_fwd_iter_v<_Iter>) { const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); if (_Count > max_size()) { _Xlen_string(); // result too long @@ -2776,7 +2776,7 @@ private: _Tidy_deallocate_guard _Guard{this}; for (; _First != _Last; ++_First) { - if constexpr (!_Is_fwd_iter_v<_Iter>) { + if constexpr (!_Is_ranges_fwd_iter_v<_Iter>) { if (_My_data._Mysize == _My_data._Myres) { // Need to grow if (_My_data._Mysize == max_size()) { _Xlen_string(); // result too long diff --git a/stl/inc/xutility b/stl/inc/xutility index c88fbe7274e..793ed3e354e 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -843,16 +843,48 @@ template struct _Is_iterator : bool_constant<_Is_iterator_v<_Ty>> {}; template -_INLINE_VAR constexpr bool _Is_input_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, input_iterator_tag>; +_INLINE_VAR constexpr bool _Is_cpp17_input_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, input_iterator_tag>; template -_INLINE_VAR constexpr bool _Is_fwd_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, forward_iterator_tag>; +_INLINE_VAR constexpr bool _Is_ranges_input_iter_v = +#ifdef __cpp_lib_concepts + (input_iterator<_Iter> && sentinel_for<_Iter, _Iter>) || +#endif + _Is_cpp17_input_iter_v<_Iter>; + +template +_INLINE_VAR constexpr bool _Is_cpp17_fwd_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, forward_iterator_tag>; + +template +_INLINE_VAR constexpr bool _Is_ranges_fwd_iter_v = +#ifdef __cpp_lib_concepts + forward_iterator<_Iter> || +#endif + _Is_cpp17_fwd_iter_v<_Iter>; + +template +_INLINE_VAR constexpr bool _Is_cpp17_bidi_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, bidirectional_iterator_tag>; template -_INLINE_VAR constexpr bool _Is_bidi_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, bidirectional_iterator_tag>; +_INLINE_VAR constexpr bool _Is_ranges_bidi_iter_v = +#ifdef __cpp_lib_concepts + bidirectional_iterator<_Iter> || +#endif + _Is_cpp17_bidi_iter_v<_Iter>; + +template +_INLINE_VAR constexpr bool _Is_cpp17_random_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, random_access_iterator_tag>; template -_INLINE_VAR constexpr bool _Is_random_iter_v = is_convertible_v<_Iter_cat_t<_Iter>, random_access_iterator_tag>; +_INLINE_VAR constexpr bool _Is_ranges_random_iter_v = +#if defined(__cpp_lib_concepts) + random_access_iterator<_Iter> || +#endif + _Is_cpp17_random_iter_v<_Iter>; + +#define _REQUIRE_CPP17_MUTABLE_ITERATOR(_Iter) \ + static_assert(_Is_cpp17_fwd_iter_v<_Iter>, \ + "Non-ranges algorithms require that mutable iterators be Cpp17ForwardIterators or stronger.") template struct _Is_checked_helper {}; // default definition, no longer used, retained due to pseudo-documentation @@ -1037,14 +1069,14 @@ template using _Enable_if_execution_policy_t = typename remove_reference_t<_ExPo>::_Standard_execution_policy; #define _REQUIRE_PARALLEL_ITERATOR(_Iter) \ - static_assert(_Is_fwd_iter_v<_Iter>, "Parallel algorithms require forward iterators or stronger.") + static_assert(_Is_ranges_fwd_iter_v<_Iter>, "Parallel algorithms require forward iterators or stronger.") #endif // _HAS_CXX17 template _NODISCARD constexpr auto _Idl_distance(const _Iter& _First, const _Iter& _Last) { // tries to get the distance between _First and _Last if they are random-access iterators - if constexpr (_Is_random_iter_v<_Iter>) { + if constexpr (_Is_ranges_random_iter_v<_Iter>) { return static_cast<_Iter_diff_t<_Checked>>(_Last - _First); } else { return _Distance_unknown{}; @@ -1098,7 +1130,7 @@ constexpr bool _Debug_lt_pred(_Pr&& _Pred, _Ty1&& _Left, _Ty2&& _Right) noexcept template constexpr void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred) { // test if range is ordered by predicate - if constexpr (_Is_fwd_iter_v<_InIt>) { + if constexpr (_Is_ranges_fwd_iter_v<_InIt>) { if (_First != _Last) { for (auto _Next = _First; ++_Next != _Last; _First = _Next) { _STL_VERIFY(!static_cast(_Pred(*_Next, *_First)), "sequence not ordered"); @@ -1110,7 +1142,7 @@ constexpr void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred template constexpr void _Debug_order_set_unchecked(_InIt _First, _InIt _Last, _Pr&& _Pred) { // test if range is ordered by predicate - if constexpr (is_same_v<_Iter_value_t<_OtherIt>, _Iter_value_t<_InIt>> && _Is_fwd_iter_v<_InIt>) { + if constexpr (is_same_v<_Iter_value_t<_OtherIt>, _Iter_value_t<_InIt>>) { _Debug_order_unchecked(_First, _Last, _Pred); } } @@ -1119,17 +1151,17 @@ constexpr void _Debug_order_set_unchecked(_InIt _First, _InIt _Last, _Pr&& _Pred // from template _CONSTEXPR17 void advance(_InIt& _Where, _Diff _Off) { // increment iterator by offset - if constexpr (_Is_random_iter_v<_InIt>) { + if constexpr (_Is_ranges_random_iter_v<_InIt>) { _Where += _Off; } else { - if constexpr (is_signed_v<_Diff> && !_Is_bidi_iter_v<_InIt>) { + if constexpr (is_signed_v<_Diff> && !_Is_ranges_bidi_iter_v<_InIt>) { _STL_ASSERT(_Off >= 0, "negative advance of non-bidirectional iterator"); } decltype(auto) _UWhere = _Get_unwrapped_n(_STD move(_Where), _Off); constexpr bool _Need_rewrap = !is_reference_v; - if constexpr (is_signed_v<_Diff> && _Is_bidi_iter_v<_InIt>) { + if constexpr (is_signed_v<_Diff> && _Is_ranges_bidi_iter_v<_InIt>) { for (; _Off < 0; ++_Off) { --_UWhere; } @@ -1147,7 +1179,7 @@ _CONSTEXPR17 void advance(_InIt& _Where, _Diff _Off) { // increment iterator by template _NODISCARD _CONSTEXPR17 _Iter_diff_t<_InIt> distance(_InIt _First, _InIt _Last) { - if constexpr (_Is_random_iter_v<_InIt>) { + if constexpr (_Is_ranges_random_iter_v<_InIt>) { return _Last - _First; // assume the iterator will do debug checking } else { _Adl_verify_range(_First, _Last); @@ -1169,7 +1201,7 @@ constexpr _InIt _Next_iter(_InIt _First) { // increment iterator template _NODISCARD _CONSTEXPR17 _InIt next(_InIt _First, _Iter_diff_t<_InIt> _Off = 1) { // increment iterator - static_assert(_Is_input_iter_v<_InIt>, "next requires input iterator"); + static_assert(_Is_ranges_input_iter_v<_InIt>, "next requires input iterator"); _STD advance(_First, _Off); return _First; @@ -1182,7 +1214,7 @@ constexpr _BidIt _Prev_iter(_BidIt _First) { // decrement iterator template _NODISCARD _CONSTEXPR17 _BidIt prev(_BidIt _First, _Iter_diff_t<_BidIt> _Off = 1) { // decrement iterator - static_assert(_Is_bidi_iter_v<_BidIt>, "prev requires bidirectional iterator"); + static_assert(_Is_ranges_bidi_iter_v<_BidIt>, "prev requires bidirectional iterator"); _STD advance(_First, -_Off); return _First; @@ -3688,7 +3720,7 @@ _FwdIt2 copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest) noexcept /* // copy [_First, _Last) to [_Dest, ...) // not parallelized as benchmarks show it isn't worth it _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD copy(_First, _Last, _Dest); } #endif // _HAS_CXX17 @@ -3828,7 +3860,7 @@ _FwdIt2 copy_n(_ExPo&&, _FwdIt1 _First, _Diff _Count_raw, _FwdIt2 _Dest) noexcep // copy [_First, _First + _Count) to [_Dest, ...) // not parallelized as benchmarks show it isn't worth it _REQUIRE_PARALLEL_ITERATOR(_FwdIt1); - _REQUIRE_PARALLEL_ITERATOR(_FwdIt2); + _REQUIRE_CPP17_MUTABLE_ITERATOR(_FwdIt2); return _STD copy_n(_First, _Count_raw, _Dest); } #endif // _HAS_CXX17 @@ -3922,8 +3954,8 @@ template && _Is_random_iter_v<_InIt2>) { + if constexpr (_Is_ranges_random_iter_v<_InIt1> && _Is_ranges_random_iter_v<_InIt2>) { if (_ULast1 - _UFirst1 != _ULast2 - _UFirst2) { return false; } @@ -5119,7 +5151,7 @@ _NODISCARD _CONSTEXPR20 bool _Check_match_counts( // test if [_First1, _Last1) == permuted [_First2, _Last2), after matching prefix removal _STL_INTERNAL_CHECK(!_Pred(*_First1, *_First2)); _STL_INTERNAL_CHECK(_STD distance(_First1, _Last1) == _STD distance(_First2, _Last2)); - if constexpr (_Is_bidi_iter_v<_FwdIt1> && _Is_bidi_iter_v<_FwdIt2>) { + if constexpr (_Is_ranges_bidi_iter_v<_FwdIt1> && _Is_ranges_bidi_iter_v<_FwdIt2>) { do { // find last inequality --_Last1; --_Last2; @@ -5232,12 +5264,12 @@ _CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { return _First; } - if constexpr (_Is_random_iter_v<_FwdIt>) { + if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { _STD reverse(_UFirst, _UMid); _STD reverse(_UMid, _ULast); _STD reverse(_UFirst, _ULast); _Seek_wrapped(_First, _UFirst + (_ULast - _UMid)); - } else if constexpr (_Is_bidi_iter_v<_FwdIt>) { + } else if constexpr (_Is_cpp17_bidi_iter_v<_FwdIt>) { _STD reverse(_UFirst, _UMid); _STD reverse(_UMid, _ULast); auto _Tmp = _Reverse_until_sentinel_unchecked(_UFirst, _UMid, _ULast); diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index b9064e29e88..311737ff44a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -270,6 +270,7 @@ // P2367R0 Remove Misuses Of List-Initialization From Clause 24 Ranges // P2372R3 Fixing Locale Handling In chrono Formatters // P2393R1 Cleaning Up Integer-Class Types +// P2408R5 Ranges Iterators As Inputs To Non-Ranges Algorithms // P2415R2 What Is A view? // P2418R2 Add Support For std::generator-like Types To std::format // P2432R1 Fix istream_view @@ -1349,6 +1350,14 @@ #endif // __cpp_impl_coroutine #if _HAS_CXX20 +#if !defined(__EDG__) || defined(__INTELLISENSE__) // TRANSITION, EDG concepts support +#define __cpp_lib_concepts 202002L +#endif // !defined(__EDG__) || defined(__INTELLISENSE__) + +#if defined(__cpp_lib_concepts) +#define __cpp_lib_algorithm_iterator_requirements 202207L +#endif + #define __cpp_lib_assume_aligned 201811L #define __cpp_lib_atomic_flag_test 201907L #define __cpp_lib_atomic_float 201711L @@ -1362,10 +1371,6 @@ #define __cpp_lib_bitops 201907L #define __cpp_lib_bounded_array_traits 201902L -#if !defined(__EDG__) || defined(__INTELLISENSE__) // TRANSITION, EDG concepts support -#define __cpp_lib_concepts 202002L -#endif // !defined(__EDG__) || defined(__INTELLISENSE__) - #define __cpp_lib_constexpr_algorithms 201806L #define __cpp_lib_constexpr_complex 201711L #define __cpp_lib_constexpr_dynamic_alloc 201907L diff --git a/tests/std/test.lst b/tests/std/test.lst index 5121260b7f6..38192912100 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -488,6 +488,7 @@ tests\P2231R1_complete_constexpr_optional_variant tests\P2273R3_constexpr_unique_ptr tests\P2321R2_proxy_reference tests\P2401R0_conditional_noexcept_for_exchange +tests\P2408R5_ranges_iterators_to_classic_algorithms tests\P2415R2_owning_view tests\P2440R1_ranges_alg_shift_left tests\P2440R1_ranges_alg_shift_right diff --git a/tests/std/tests/P2408R5_ranges_iterators_to_classic_algorithms/env.lst b/tests/std/tests/P2408R5_ranges_iterators_to_classic_algorithms/env.lst new file mode 100644 index 00000000000..7b6bcff4830 --- /dev/null +++ b/tests/std/tests/P2408R5_ranges_iterators_to_classic_algorithms/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_20_matrix.lst diff --git a/tests/std/tests/P2408R5_ranges_iterators_to_classic_algorithms/test.cpp b/tests/std/tests/P2408R5_ranges_iterators_to_classic_algorithms/test.cpp new file mode 100644 index 00000000000..b2d59b49ebd --- /dev/null +++ b/tests/std/tests/P2408R5_ranges_iterators_to_classic_algorithms/test.cpp @@ -0,0 +1,194 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +template +using second = U; +template +Input second_v(Input x) { + return x; +} + +template +struct iterator_adaptor { + vector v; + iterator_adaptor(initializer_list il) : v(il) {} + iterator_adaptor(size_t n) : v(n) {} + + using iterator = I; + using const_iterator = typename I::Consterator; + + iterator begin() { + return iterator{v.data()}; + } + iterator end() { + return iterator{v.data() + v.size()}; + } + + const_iterator cbegin() const { + return const_iterator{v.data()}; + } + const_iterator cend() const { + return const_iterator{v.data() + v.size()}; + } +}; + +template +struct helper { + helper(second>... ils) : tup(ils...) {} + + helper(initializer_list il) requires(sizeof...(Is) > 1) : tup(second_v(il.size())...) { + get<0>(tup).v.assign(il); + } + + tuple...> tup; +}; + +template +auto hbegin(helper& h) { + return get(h.tup).begin(); +} +template +auto hend(helper& h) { + return get(h.tup).end(); +} + +template +auto hcbegin(const helper& h) { + return get(h.tup).cbegin(); +} +template +auto hcend(const helper& h) { + return get(h.tup).cend(); +} + +template +struct unary_algorithms { + static void call() { + if constexpr (forward_iterator) { + // parallel algorithms + using execution::seq; + { + helper h({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + auto res = reduce(seq, hcbegin<0>(h), hcend<0>(h), 0); + assert(res == 55); + } + } + } +}; + +template +struct binary_algorithms { + static void call() { + if constexpr (forward_iterator || _Is_cpp17_fwd_iter_v) { + helper h({0, 0, 1, 2, 3, 3, 4, 5}); + array exp{0, 1, 2, 3, 4, 5}; + auto it = unique_copy(hcbegin<0>(h), hcend<0>(h), hbegin<1>(h)); + assert(equal(hbegin<1>(h), it, exp.begin(), exp.end())); + } + + if constexpr (forward_iterator && forward_iterator) { + { + helper h{{0, 1, 2, 3, 4, 5}, {5, 4, 3, 2, 1, 0}}; + assert(is_permutation(hcbegin<0>(h), hcend<0>(h), hcbegin<1>(h), hcend<1>(h))); + } + + // parallel algorithms + using execution::seq; + { + helper h{{0, 1, 2, 3, 4, 5}, {0, 1, 3, 4, 5}}; + auto pr = mismatch(seq, hcbegin<0>(h), hcend<0>(h), hcbegin<1>(h), hcend<1>(h)); + assert(distance(hcbegin<0>(h), pr.first) == 2); + assert(*pr.first == 2); + assert(*pr.second == 3); + } + if constexpr (_Is_cpp17_fwd_iter_v) { + helper h{{0, 1, 2, 3, 4, 5}}; + array expected{0, 1, 2, 4, 5}; + auto it = copy_if(seq, hcbegin<0>(h), hcend<0>(h), hbegin<1>(h), [](int x) { return x != 3; }); + assert(equal(hbegin<1>(h), it, expected.begin(), expected.end())); + } + } + } +}; + +template +struct ternary_algorithms { + static void call() { + if constexpr (forward_iterator && forward_iterator && forward_iterator) { + // parallel algorithms + using execution::seq; + if constexpr (_Is_cpp17_fwd_iter_v && _Is_cpp17_fwd_iter_v) { + helper h{{0, 1, 2, 3, 4, 5}}; + array exp1{0, 1}; + array exp2{2, 3, 4, 5}; + auto pr = partition_copy( + seq, hcbegin<0>(h), hcend<0>(h), hbegin<1>(h), hbegin<2>(h), [](int x) { return x < 2; }); + assert(equal(hbegin<1>(h), pr.first, exp1.begin(), exp1.end())); + assert(equal(hbegin<2>(h), pr.second, exp2.begin(), exp2.end())); + } + } + } +}; + +using input_iter = test::iterator; +using fwd_iter = test::iterator; +using bidi_iter = test::iterator; +using random_iter = test::iterator; +using cpp17_fwd_iter = + test::iterator; +using cpp17_bidi_iter = + test::iterator; +using cpp17_random_iter = test::iterator; + +// Sanity checks +static_assert(!_Is_cpp17_fwd_iter_v && !forward_iterator); +static_assert(!_Is_cpp17_fwd_iter_v && forward_iterator); +static_assert(!_Is_cpp17_fwd_iter_v && bidirectional_iterator); +static_assert(!_Is_cpp17_fwd_iter_v && random_access_iterator); +static_assert(_Is_cpp17_fwd_iter_v && forward_iterator); +static_assert(_Is_cpp17_bidi_iter_v && bidirectional_iterator); +static_assert(_Is_cpp17_random_iter_v && random_access_iterator); + +template