diff --git a/llvm-project b/llvm-project index 85ee4ff4e47..6d8abe424a7 160000 --- a/llvm-project +++ b/llvm-project @@ -1 +1 @@ -Subproject commit 85ee4ff4e474788abc7abdc939114281c2a68ec1 +Subproject commit 6d8abe424a77f736fbed114eeac574b9bfe6b0c1 diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 1ed36d82b42..77777c5b4b5 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -80,7 +80,7 @@ struct _Optimistic_temporary_buffer { // temporary storage with _alloca-like att // FUNCTION TEMPLATE for_each template -_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last) +_CONSTEXPR20 _Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last) _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -97,7 +97,7 @@ void for_each(_ExPo&& _Exec, _FwdIt _First, _FwdIt _Last, _Fn _Func) noexcept; / // FUNCTION TEMPLATE for_each_n template -_InIt for_each_n(_InIt _First, const _Diff _Count_raw, _Fn _Func) { +_CONSTEXPR20 _InIt for_each_n(_InIt _First, const _Diff _Count_raw, _Fn _Func) { // perform function for each element [_First, _First + _Count) _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { @@ -119,7 +119,7 @@ _FwdIt for_each_n(_ExPo&& _Exec, _FwdIt _First, _Diff _Count_raw, _Fn _Func) noe #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_InTy* for_each_n(_InTy (&_First)[_InSize], const _Diff _Count_raw, _Fn _Func) { +_CONSTEXPR20 _InTy* for_each_n(_InTy (&_First)[_InSize], const _Diff _Count_raw, _Fn _Func) { // perform function for each element [_First, _First + _Count) _Algorithm_int_t<_Diff> _Count = _Count_raw; _STL_VERIFY_ARRAY_SIZE(_First, _Count); @@ -146,7 +146,8 @@ _NODISCARD _FwdIt find_if(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _Pr // FUNCTION TEMPLATE find_if_not template -_NODISCARD _InIt find_if_not(_InIt _First, const _InIt _Last, _Pr _Pred) { // find first element that satisfies !_Pred +_NODISCARD _CONSTEXPR20 _InIt find_if_not(_InIt _First, const _InIt _Last, _Pr _Pred) { + // find first element that satisfies !_Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -167,7 +168,7 @@ _NODISCARD _FwdIt find_if_not(_ExPo&& _Exec, _FwdIt _First, _FwdIt _Last, _Pr _P // FUNCTION TEMPLATE adjacent_find template -_NODISCARD _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find first satisfying _Pred with successor _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -186,7 +187,7 @@ _NODISCARD _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { } template -_NODISCARD _FwdIt adjacent_find(const _FwdIt _First, const _FwdIt _Last) { // find first matching successor +_NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, const _FwdIt _Last) { // find first matching successor return _STD adjacent_find(_First, _Last, equal_to<>()); } @@ -203,7 +204,8 @@ _NODISCARD _FwdIt adjacent_find(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt // FUNCTION TEMPLATE count_if template -_NODISCARD _Iter_diff_t<_InIt> count_if(_InIt _First, _InIt _Last, _Pr _Pred) { // count elements satisfying _Pred +_NODISCARD _CONSTEXPR20 _Iter_diff_t<_InIt> count_if(_InIt _First, _InIt _Last, _Pr _Pred) { + // count elements satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -225,7 +227,7 @@ _NODISCARD _Iter_diff_t<_FwdIt> count_if( // FUNCTION TEMPLATE mismatch template -_NODISCARD pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Pr _Pred) { // return [_First1, _Last1)/[_First2, ...) mismatch using _Pred _Adl_verify_range(_First1, _Last1); auto _UFirst1 = _Get_unwrapped(_First1); @@ -243,8 +245,9 @@ _NODISCARD pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InIt1 _Last1, _I #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template , int> = 0> -_NODISCARD pair<_InIt1, _RightTy*> mismatch(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], - _Pr _Pred) { // return [_First1, _Last1)/[_First2, ...) mismatch using _Pred +_NODISCARD _CONSTEXPR20 pair<_InIt1, _RightTy*> mismatch( + const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], _Pr _Pred) { + // return [_First1, _Last1)/[_First2, ...) mismatch using _Pred const auto _Result = _STD mismatch(_First1, _Last1, _Array_iterator<_RightTy, _RightSize>(_First2), _Pass_fn(_Pred)); return {_Result.first, _Result.second._Unwrapped()}; @@ -270,14 +273,14 @@ _NODISCARD pair<_FwdIt1, _RightTy*> mismatch(_ExPo&& _Exec, const _FwdIt1 _First #endif // _HAS_CXX17 template -_NODISCARD pair<_InIt1, _InIt2> mismatch(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2) { +_NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2) { // return [_First1, _Last1)/[_First2, ...) mismatch return _STD mismatch(_First1, _Last1, _First2, equal_to<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_NODISCARD pair<_InIt1, _RightTy*> mismatch( +_NODISCARD _CONSTEXPR20 pair<_InIt1, _RightTy*> mismatch( const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize]) { // return [_First1, _Last1)/[_First2, ...) mismatch, array source return _STD mismatch(_First1, _Last1, _First2, equal_to<>()); @@ -307,7 +310,8 @@ _NODISCARD pair<_FwdIt1, _RightTy*> mismatch(_ExPo&& _Exec, const _FwdIt1 _First #if _HAS_IF_CONSTEXPR template -_NODISCARD pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { // return [_First1, _Last1)/[_First2, _Last2) mismatch using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -380,7 +384,7 @@ _NODISCARD pair<_FwdIt1, _FwdIt2> mismatch( #endif // _HAS_CXX17 template -_NODISCARD pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { +_NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { // return [_First1, _Last1)/[_First2, _Last2) mismatch return _STD mismatch(_First1, _Last1, _First2, _Last2, equal_to<>()); } @@ -398,7 +402,7 @@ _NODISCARD pair<_FwdIt1, _FwdIt2> mismatch( // FUNCTION TEMPLATE all_of template -_NODISCARD bool all_of(_InIt _First, _InIt _Last, _Pr _Pred) { // test if all elements satisfy _Pred +_NODISCARD _CONSTEXPR20 bool all_of(_InIt _First, _InIt _Last, _Pr _Pred) { // test if all elements satisfy _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -418,7 +422,8 @@ _NODISCARD bool all_of(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept // FUNCTION TEMPLATE any_of template -_NODISCARD bool any_of(const _InIt _First, const _InIt _Last, _Pr _Pred) { // test if any element satisfies _Pred +_NODISCARD _CONSTEXPR20 bool any_of(const _InIt _First, const _InIt _Last, _Pr _Pred) { + // test if any element satisfies _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -438,7 +443,8 @@ _NODISCARD bool any_of(_ExPo&&, const _FwdIt _First, const _FwdIt _Last, _Pr _Pr // FUNCTION TEMPLATE none_of template -_NODISCARD bool none_of(const _InIt _First, const _InIt _Last, _Pr _Pred) { // test if no elements satisfy _Pred +_NODISCARD _CONSTEXPR20 bool none_of(const _InIt _First, const _InIt _Last, _Pr _Pred) { + // test if no elements satisfy _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -458,7 +464,7 @@ _NODISCARD bool none_of(_ExPo&&, const _FwdIt _First, const _FwdIt _Last, _Pr _P // FUNCTION TEMPLATE copy_if template -_OutIt copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy each satisfying _Pred +_CONSTEXPR20 _OutIt copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy each satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -476,7 +482,7 @@ _OutIt copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy eac #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* copy_if(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { +_CONSTEXPR20 _DestTy* copy_if(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // copy each satisfying _Pred, array dest return _STD copy_if(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Pred))._Unwrapped(); } @@ -507,7 +513,8 @@ _DestTy* copy_if( // FUNCTION TEMPLATE partition_copy template -pair<_OutIt1, _OutIt2> partition_copy(_InIt _First, _InIt _Last, _OutIt1 _Dest_true, _OutIt2 _Dest_false, _Pr _Pred) { +_CONSTEXPR20 pair<_OutIt1, _OutIt2> partition_copy( + _InIt _First, _InIt _Last, _OutIt1 _Dest_true, _OutIt2 _Dest_false, _Pr _Pred) { // copy true partition to _Dest_true, false to _Dest_false _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -531,15 +538,16 @@ pair<_OutIt1, _OutIt2> partition_copy(_InIt _First, _InIt _Last, _OutIt1 _Dest_t #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -pair<_DestTrueTy*, _OutIt2> partition_copy(_InIt _First, _InIt _Last, _DestTrueTy (&_Dest_true)[_DestTrueSize], - _OutIt2 _Dest_false, _Pr _Pred) { // copy true partition to _Dest_true, false to _Dest_false, array dest +_CONSTEXPR20 pair<_DestTrueTy*, _OutIt2> partition_copy( + _InIt _First, _InIt _Last, _DestTrueTy (&_Dest_true)[_DestTrueSize], _OutIt2 _Dest_false, _Pr _Pred) { + // copy true partition to _Dest_true, false to _Dest_false, array dest const auto _Result = _STD partition_copy( _First, _Last, _Array_iterator<_DestTrueTy, _DestTrueSize>(_Dest_true), _Dest_false, _Pass_fn(_Pred)); return {_Result.first._Unwrapped(), _Result.second}; } template -pair<_OutIt1, _DestFalseTy*> partition_copy( +_CONSTEXPR20 pair<_OutIt1, _DestFalseTy*> partition_copy( _InIt _First, _InIt _Last, _OutIt1 _Dest_true, _DestFalseTy (&_Dest_false)[_DestFalseSize], _Pr _Pred) { // copy true partition to _Dest_true, false to _Dest_false, array dest const auto _Result = _STD partition_copy( @@ -548,8 +556,8 @@ pair<_OutIt1, _DestFalseTy*> partition_copy( } template -pair<_DestTrueTy*, _DestFalseTy*> partition_copy(_InIt _First, _InIt _Last, _DestTrueTy (&_Dest_true)[_DestTrueSize], - _DestFalseTy (&_Dest_false)[_DestFalseSize], _Pr _Pred) { +_CONSTEXPR20 pair<_DestTrueTy*, _DestFalseTy*> partition_copy(_InIt _First, _InIt _Last, + _DestTrueTy (&_Dest_true)[_DestTrueSize], _DestFalseTy (&_Dest_false)[_DestFalseSize], _Pr _Pred) { // copy true partition to _Dest_true, false to _Dest_false, array dest const auto _Result = _STD partition_copy(_First, _Last, _Array_iterator<_DestTrueTy, _DestTrueSize>(_Dest_true), _Array_iterator<_DestFalseTy, _DestFalseSize>(_Dest_false), _Pass_fn(_Pred)); @@ -607,7 +615,7 @@ pair<_DestTrueTy*, _DestFalseTy*> partition_copy(_ExPo&&, _FwdIt1 _First, _FwdIt // FUNCTION TEMPLATE is_partitioned template -_NODISCARD bool is_partitioned(const _InIt _First, const _InIt _Last, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool is_partitioned(const _InIt _First, const _InIt _Last, _Pr _Pred) { // test if [_First, _Last) partitioned by _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -639,7 +647,7 @@ _NODISCARD bool is_partitioned(_ExPo&&, const _FwdIt _First, const _FwdIt _Last, // FUNCTION TEMPLATE partition_point template -_NODISCARD _FwdIt partition_point(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _FwdIt partition_point(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find beginning of false partition in [_First, _Last) _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -665,22 +673,28 @@ _NODISCARD _FwdIt partition_point(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // FUNCTION TEMPLATE _Equal_rev_pred_unchecked #if _HAS_IF_CONSTEXPR template -bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20_ICE bool _Equal_rev_pred_unchecked( + _InIt1 _First1, _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { // compare [_First1, ...) to [_First2, _Last2) using _Pred if constexpr (decltype(_Equal_memcmp_is_safe(_First1, _First2, _Pred))::value) { - const auto _First1_ch = reinterpret_cast(_First1); - const auto _First2_ch = reinterpret_cast(_First2); - const auto _Count = static_cast(reinterpret_cast(_Last2) - _First2_ch); - return _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0; - } else { - for (; _First2 != _Last2; ++_First1, (void) ++_First2) { - if (!_Pred(*_First1, *_First2)) { - return false; - } +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _First1_ch = reinterpret_cast(_First1); + const auto _First2_ch = reinterpret_cast(_First2); + const auto _Count = static_cast(reinterpret_cast(_Last2) - _First2_ch); + return _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0; } + } - return true; + for (; _First2 != _Last2; ++_First1, (void) ++_First2) { + if (!_Pred(*_First1, *_First2)) { + return false; + } } + + return true; } #else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv template @@ -714,8 +728,8 @@ bool _Equal_rev_pred_unchecked(const _InIt1 _First1, const _InIt2 _First2, const // FUNCTION TEMPLATE search #if _HAS_IF_CONSTEXPR template -_NODISCARD _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHaystack _Last1, const _FwdItPat _First2, - const _FwdItPat _Last2, _Pr _Pred) { // find first [_First2, _Last2) satisfying _Pred +_NODISCARD _CONSTEXPR20_ICE _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHaystack _Last1, + const _FwdItPat _First2, const _FwdItPat _Last2, _Pr _Pred) { // find first [_First2, _Last2) satisfying _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); auto _UFirst1 = _Get_unwrapped(_First1); @@ -814,8 +828,9 @@ _NODISCARD _FwdItHaystack search(_ExPo&& _Exec, const _FwdItHaystack _First1, _F #endif // _HAS_CXX17 template -_NODISCARD _FwdItHaystack search(const _FwdItHaystack _First1, const _FwdItHaystack _Last1, const _FwdItPat _First2, - const _FwdItPat _Last2) { // find first [_First2, _Last2) match +_NODISCARD _CONSTEXPR20_ICE _FwdItHaystack search( + const _FwdItHaystack _First1, const _FwdItHaystack _Last1, const _FwdItPat _First2, const _FwdItPat _Last2) { + // find first [_First2, _Last2) match return _STD search(_First1, _Last1, _First2, _Last2, equal_to<>()); } @@ -829,7 +844,8 @@ _NODISCARD _FwdItHaystack search(_ExPo&& _Exec, const _FwdItHaystack _First1, co #endif // _HAS_CXX17 template -_NODISCARD _FwdItHaystack search(const _FwdItHaystack _First, const _FwdItHaystack _Last, const _Searcher& _Search) { +_NODISCARD _CONSTEXPR20 _FwdItHaystack search( + const _FwdItHaystack _First, const _FwdItHaystack _Last, const _Searcher& _Search) { // find _Search's pattern in [_First, _Last) return _Search(_First, _Last).first; } @@ -837,7 +853,8 @@ _NODISCARD _FwdItHaystack search(const _FwdItHaystack _First, const _FwdItHaysta // FUNCTION TEMPLATE search_n #if _HAS_IF_CONSTEXPR template -_NODISCARD _FwdIt search_n(const _FwdIt _First, _FwdIt _Last, const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _FwdIt search_n( + const _FwdIt _First, _FwdIt _Last, const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred) { // find first _Count * _Val satisfying _Pred const _Algorithm_int_t<_Diff> _Count = _Count_raw; if (_Count <= 0) { @@ -996,8 +1013,8 @@ _NODISCARD _FwdIt search_n(_ExPo&& _Exec, const _FwdIt _First, _FwdIt _Last, con #endif // _HAS_CXX17 template -_NODISCARD _FwdIt search_n( - const _FwdIt _First, const _FwdIt _Last, const _Diff _Count, const _Ty& _Val) { // find first _Count * _Val match +_NODISCARD _CONSTEXPR20 _FwdIt search_n(const _FwdIt _First, const _FwdIt _Last, const _Diff _Count, const _Ty& _Val) { + // find first _Count * _Val match return _STD search_n(_First, _Last, _Count, _Val, equal_to<>()); } @@ -1012,8 +1029,9 @@ _NODISCARD _FwdIt search_n(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Las // FUNCTION TEMPLATE find_end #if _HAS_IF_CONSTEXPR template -_NODISCARD _FwdIt1 find_end(_FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2, - _Pr _Pred) { // find last [_First2, _Last2) satisfying _Pred +_NODISCARD _CONSTEXPR20 _FwdIt1 find_end( + _FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2, _Pr _Pred) { + // find last [_First2, _Last2) satisfying _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); auto _UFirst1 = _Get_unwrapped(_First1); @@ -1182,7 +1200,8 @@ _NODISCARD _FwdIt1 find_end(_FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 #endif // _HAS_IF_CONSTEXPR template -_NODISCARD _FwdIt1 find_end(_FwdIt1 const _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2) { +_NODISCARD _CONSTEXPR20 _FwdIt1 find_end( + _FwdIt1 const _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2) { // find last [_First2, _Last2) match return _STD find_end(_First1, _Last1, _First2, _Last2, equal_to<>()); } @@ -1201,8 +1220,9 @@ _NODISCARD _FwdIt1 find_end(_ExPo&& _Exec, _FwdIt1 _First1, _FwdIt1 _Last1, _Fwd // FUNCTION TEMPLATE find_first_of template -_NODISCARD _FwdIt1 find_first_of(_FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2, - _Pr _Pred) { // look for one of [_First2, _Last2) satisfying _Pred with element +_NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of( + _FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2, _Pr _Pred) { + // look for one of [_First2, _Last2) satisfying _Pred with element _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); auto _UFirst1 = _Get_unwrapped(_First1); @@ -1223,7 +1243,7 @@ _NODISCARD _FwdIt1 find_first_of(_FwdIt1 _First1, const _FwdIt1 _Last1, const _F } template -_NODISCARD _FwdIt1 find_first_of(const _FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, +_NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of(const _FwdIt1 _First1, const _FwdIt1 _Last1, const _FwdIt2 _First2, const _FwdIt2 _Last2) { // look for one of [_First2, _Last2) that matches element return _STD find_first_of(_First1, _Last1, _First2, _Last2, equal_to<>()); } @@ -1243,7 +1263,7 @@ _NODISCARD _FwdIt1 find_first_of(_ExPo&& _Exec, const _FwdIt1 _First1, const _Fw // FUNCTION TEMPLATE swap_ranges template -_FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { +_CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { // swap [_First1, _Last1) with [_First2, ...), no special optimization for (; _First1 != _Last1; ++_First1, (void) ++_First2) { _STD iter_swap(_First1, _First2); @@ -1254,15 +1274,26 @@ _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _F #if (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) template , int> = 0> -_Ty* _Swap_ranges_unchecked(_Ty* const _First1, _Ty* const _Last1, _Ty* const _First2) { +_CONSTEXPR20_ICE _Ty* _Swap_ranges_unchecked(_Ty* _First1, _Ty* const _Last1, _Ty* _First2) { // swap [_First1, _Last1) with [_First2, ...), trivially swappable optimization - __std_swap_ranges_trivially_swappable_noalias(_First1, _Last1, _First2); - return _First2 + (_Last1 - _First1); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + __std_swap_ranges_trivially_swappable_noalias(_First1, _Last1, _First2); + return _First2 + (_Last1 - _First1); + } + + for (; _First1 != _Last1; ++_First1, (void) ++_First2) { + _STD iter_swap(_First1, _First2); + } + + return _First2; } #endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) template -_FwdIt2 swap_ranges(const _FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { +_CONSTEXPR20_ICE _FwdIt2 swap_ranges(const _FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { // swap [_First1, _Last1) with [_First2, ...) _Adl_verify_range(_First1, _Last1); const auto _UFirst1 = _Get_unwrapped(_First1); @@ -1274,7 +1305,7 @@ _FwdIt2 swap_ranges(const _FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2 #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* swap_ranges(_FwdIt1 _First1, _FwdIt1 _Last1, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20_ICE _DestTy* swap_ranges(_FwdIt1 _First1, _FwdIt1 _Last1, _DestTy (&_Dest)[_DestSize]) { // swap [_First1, _Last1) with [_Dest, ...), array dest return _STD swap_ranges(_First1, _Last1, _Array_iterator<_DestTy, _DestSize>(_Dest))._Unwrapped(); } @@ -1300,7 +1331,7 @@ _DestTy* swap_ranges(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _DestTy (&_Dest)[ // FUNCTION TEMPLATE transform template -_OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func) { +_CONSTEXPR20 _OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func) { // transform [_First, _Last) with _Func _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1316,7 +1347,7 @@ _OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func) #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* transform(const _InIt _First, const _InIt _Last, _DestTy (&_Dest)[_DestSize], _Fn _Func) { +_CONSTEXPR20 _DestTy* transform(const _InIt _First, const _InIt _Last, _DestTy (&_Dest)[_DestSize], _Fn _Func) { // transform [_First, _Last) with _Func, array dest return _STD transform(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Func))._Unwrapped(); } @@ -1341,7 +1372,8 @@ _DestTy* transform( #endif // _HAS_CXX17 template -_OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest, _Fn _Func) { +_CONSTEXPR20 _OutIt transform( + const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest, _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...) with _Func _Adl_verify_range(_First1, _Last1); auto _UFirst1 = _Get_unwrapped(_First1); @@ -1359,21 +1391,24 @@ _OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2 #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], const _OutIt _Dest, - _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...), array source +_CONSTEXPR20 _OutIt transform( + const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], const _OutIt _Dest, _Fn _Func) { + // transform [_First1, _Last1) and [_First2, ...), array source return _STD transform(_First1, _Last1, _Array_iterator<_RightTy, _RightSize>(_First2), _Dest, _Pass_fn(_Func)); } template -_DestTy* transform(const _InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _DestTy (&_Dest)[_DestSize], - _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...), array dest +_CONSTEXPR20 _DestTy* transform( + const _InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _DestTy (&_Dest)[_DestSize], _Fn _Func) { + // transform [_First1, _Last1) and [_First2, ...), array dest return _STD transform(_First1, _Last1, _First2, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Func)) ._Unwrapped(); } template -_DestTy* transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], - _DestTy (&_Dest)[_DestSize], _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...), array source/dest +_CONSTEXPR20 _DestTy* transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], + _DestTy (&_Dest)[_DestSize], _Fn _Func) { + // transform [_First1, _Last1) and [_First2, ...), array source/dest return _STD transform(_First1, _Last1, _Array_iterator<_RightTy, _RightSize>(_First2), _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Func)) ._Unwrapped(); @@ -1419,7 +1454,7 @@ _DestTy* transform(_ExPo&& _Exec, const _FwdIt1 _First1, const _FwdIt1 _Last1, _ // FUNCTION TEMPLATE replace template -void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval) { +_CONSTEXPR20 void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval) { // replace each matching _Oldval with _Newval _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1439,7 +1474,7 @@ void replace(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, const _Ty& // FUNCTION TEMPLATE replace_if template -void replace_if(const _FwdIt _First, const _FwdIt _Last, _Pr _Pred, const _Ty& _Val) { +_CONSTEXPR20 void replace_if(const _FwdIt _First, const _FwdIt _Last, _Pr _Pred, const _Ty& _Val) { // replace each satisfying _Pred with _Val _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1458,7 +1493,7 @@ void replace_if(_ExPo&& _Exec, _FwdIt _First, _FwdIt _Last, _Pr _Pred, const _Ty // FUNCTION TEMPLATE replace_copy template -_OutIt replace_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Oldval, const _Ty& _Newval) { +_CONSTEXPR20 _OutIt replace_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Oldval, const _Ty& _Newval) { // copy replacing each matching _Oldval with _Newval _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1478,7 +1513,8 @@ _OutIt replace_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Oldval, #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* replace_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], const _Ty& _Oldval, const _Ty& _Newval) { +_CONSTEXPR20 _DestTy* replace_copy( + _InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], const _Ty& _Oldval, const _Ty& _Newval) { // copy replacing each matching _Oldval with _Newval, array dest return _STD replace_copy(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Oldval, _Newval)._Unwrapped(); } @@ -1510,7 +1546,7 @@ _DestTy* replace_copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _DestTy (&_Dest)[_ // FUNCTION TEMPLATE replace_copy_if template -_OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const _Ty& _Val) { +_CONSTEXPR20 _OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const _Ty& _Val) { // copy replacing each satisfying _Pred with _Val _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1530,7 +1566,8 @@ _OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* replace_copy_if(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred, const _Ty& _Val) { +_CONSTEXPR20 _DestTy* replace_copy_if( + _InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred, const _Ty& _Val) { // copy replacing each satisfying _Pred with _Val, array dest return _STD replace_copy_if(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Pred), _Val) ._Unwrapped(); @@ -1563,7 +1600,7 @@ _DestTy* replace_copy_if(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _DestTy (&_Dest // FUNCTION TEMPLATE generate template -void generate(_FwdIt _First, _FwdIt _Last, _Fn _Func) { // replace [_First, _Last) with _Func() +_CONSTEXPR20 void generate(_FwdIt _First, _FwdIt _Last, _Fn _Func) { // replace [_First, _Last) with _Func() _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -1583,7 +1620,8 @@ void generate(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Fn _Func) noexcept /* termi // FUNCTION TEMPLATE generate_n template -_OutIt generate_n(_OutIt _Dest, const _Diff _Count_raw, _Fn _Func) { // replace [_Dest, _Dest + _Count) with _Func() +_CONSTEXPR20 _OutIt generate_n(_OutIt _Dest, const _Diff _Count_raw, _Fn _Func) { + // replace [_Dest, _Dest + _Count) with _Func() _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { auto _UDest = _Get_unwrapped_n(_Dest, _Count); @@ -1601,7 +1639,7 @@ _OutIt generate_n(_OutIt _Dest, const _Diff _Count_raw, _Fn _Func) { // replace #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* generate_n(_DestTy (&_Dest)[_DestSize], const _Diff _Count_raw, _Fn _Func) { +_CONSTEXPR20 _DestTy* generate_n(_DestTy (&_Dest)[_DestSize], const _Diff _Count_raw, _Fn _Func) { // replace [_Dest, _Dest + _Count) with _Func(), array dest _Algorithm_int_t<_Diff> _Count = _Count_raw; _STL_VERIFY_ARRAY_SIZE(_Dest, _Count); @@ -1636,7 +1674,8 @@ _DestTy* generate_n(_ExPo&&, _DestTy (&_Dest)[_DestSize], const _Diff _Count_raw // FUNCTION TEMPLATE remove_copy template -_OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Val) { // copy omitting each matching _Val +_CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Val) { + // copy omitting each matching _Val _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -1654,7 +1693,7 @@ _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Val) { / #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* remove_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], const _Ty& _Val) { +_CONSTEXPR20 _DestTy* remove_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], const _Ty& _Val) { // copy omitting each matching _Val, array dest return _STD remove_copy(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Val)._Unwrapped(); } @@ -1685,7 +1724,7 @@ _DestTy* remove_copy( // FUNCTION TEMPLATE remove_copy_if template -_OutIt remove_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { +_CONSTEXPR20 _OutIt remove_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy omitting each element satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1704,7 +1743,7 @@ _OutIt remove_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* remove_copy_if(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { +_CONSTEXPR20 _DestTy* remove_copy_if(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // copy omitting each element satisfying _Pred, array dest return _STD remove_copy_if(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Pred))._Unwrapped(); } @@ -1746,7 +1785,8 @@ _NODISCARD _FwdIt remove_if(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _P // FUNCTION TEMPLATE unique template -_NODISCARD _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred with previous +_NODISCARD _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { + // remove each satisfying _Pred with previous _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -1770,7 +1810,7 @@ _NODISCARD _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // remove eac } template -_NODISCARD _FwdIt unique(_FwdIt _First, _FwdIt _Last) { // remove each matching previous +_NODISCARD _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last) { // remove each matching previous return _STD unique(_First, _Last, equal_to<>()); } @@ -1804,7 +1844,8 @@ _INLINE_VAR constexpr bool _Can_reread_dest = // clang-format on template -_OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy compressing pairs that match +_CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { + // copy compressing pairs that match _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -1937,20 +1978,20 @@ _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* unique_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { +_CONSTEXPR20 _DestTy* unique_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // copy compressing pairs that match, array dest return _STD unique_copy(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Pred))._Unwrapped(); } #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy compressing pairs that match +_CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy compressing pairs that match return _STD unique_copy(_First, _Last, _Dest, equal_to<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* unique_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20 _DestTy* unique_copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize]) { // copy compressing pairs that match, array dest return _STD unique_copy(_First, _Last, _Dest, equal_to<>()); } @@ -2000,7 +2041,7 @@ _DestTy* unique_copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _DestTy (&_Dest)[_D // FUNCTION TEMPLATE reverse_copy template -_OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { +_CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { // copy reversing elements in [_First, _Last) _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); @@ -2016,7 +2057,7 @@ _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* reverse_copy(_BidIt _First, _BidIt _Last, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20 _DestTy* reverse_copy(_BidIt _First, _BidIt _Last, _DestTy (&_Dest)[_DestSize]) { // copy reversing elements in [_First, _Last), array dest return _STD reverse_copy(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest))._Unwrapped(); } @@ -2043,7 +2084,8 @@ _DestTy* reverse_copy(_ExPo&&, _BidIt _First, _BidIt _Last, _DestTy (&_Dest)[_De // FUNCTION TEMPLATE rotate_copy template -_OutIt rotate_copy(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last, _OutIt _Dest) { // copy rotating [_First, _Last) +_CONSTEXPR20_ICE _OutIt rotate_copy(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last, _OutIt _Dest) { + // copy rotating [_First, _Last) _Adl_verify_range(_First, _Mid); _Adl_verify_range(_Mid, _Last); const auto _UFirst = _Get_unwrapped(_First); @@ -2346,7 +2388,7 @@ _FwdIt shift_right(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Iter_diff_t<_FwdIt> _P // FUNCTION TEMPLATE partition #if _HAS_IF_CONSTEXPR template -_FwdIt partition(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { +_CONSTEXPR20 _FwdIt partition(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { // move elements satisfying _Pred to beginning of sequence _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -2644,7 +2686,8 @@ _BidIt stable_partition(_ExPo&&, _BidIt _First, _BidIt _Last, _Pr _Pred) noexcep // FUNCTION TEMPLATE push_heap template -void _Push_heap_by_index(_RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Top, _Ty&& _Val, _Pr _Pred) { +_CONSTEXPR20 void _Push_heap_by_index( + _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Top, _Ty&& _Val, _Pr _Pred) { // percolate _Hole to _Top or where _Val belongs, using _Pred using _Diff = _Iter_diff_t<_RanIt>; for (_Diff _Idx = (_Hole - 1) >> 1; // shift for codegen @@ -2659,7 +2702,7 @@ void _Push_heap_by_index(_RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t } template -void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // push *(_Last - 1) onto heap at [_First, _Last - 1), using _Pred _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); @@ -2673,15 +2716,17 @@ void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { } template -void push_heap(_RanIt _First, _RanIt _Last) { // push *(_Last - 1) onto heap at [_First, _Last - 1), using operator< +_CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last) { + // push *(_Last - 1) onto heap at [_First, _Last - 1), using operator< _STD push_heap(_First, _Last, less<>()); } // FUNCTION TEMPLATE pop_heap template -void _Pop_heap_hole_by_index(_RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Bottom, _Ty&& _Val, - _Pr _Pred) { // percolate _Hole to _Bottom, then push _Val, using _Pred - // precondition: _Bottom != 0 +_CONSTEXPR20 void _Pop_heap_hole_by_index( + _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Bottom, _Ty&& _Val, _Pr _Pred) { + // percolate _Hole to _Bottom, then push _Val, using _Pred + _STL_INTERNAL_CHECK(_Bottom != 0); using _Diff = _Iter_diff_t<_RanIt>; const _Diff _Top = _Hole; _Diff _Idx = _Hole; @@ -2707,7 +2752,7 @@ void _Pop_heap_hole_by_index(_RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_di } template -void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty&& _Val, _Pr _Pred) { +_CONSTEXPR20 void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty&& _Val, _Pr _Pred) { // pop *_First to *_Dest and reheap, using _Pred // precondition: _First != _Last // precondition: _First != _Dest @@ -2717,7 +2762,7 @@ void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty&& _ } template -void _Pop_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 void _Pop_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // pop *_First to *(_Last - 1) and reheap, using _Pred if (2 <= _Last - _First) { --_Last; @@ -2727,19 +2772,21 @@ void _Pop_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { } template -void pop_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // pop *_First to *(_Last - 1) and reheap, using _Pred +_CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // pop *_First to *(_Last - 1) and reheap, using _Pred _Adl_verify_range(_First, _Last); _Pop_heap_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Pass_fn(_Pred)); } template -void pop_heap(_RanIt _First, _RanIt _Last) { // pop *_First to *(_Last - 1) and reheap, using operator< +_CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last) { + // pop *_First to *(_Last - 1) and reheap, using operator< _STD pop_heap(_First, _Last, less<>()); } // FUNCTION TEMPLATE make_heap template -void _Make_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 void _Make_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // make nontrivial [_First, _Last) into a heap, using _Pred using _Diff = _Iter_diff_t<_RanIt>; _Diff _Bottom = _Last - _First; @@ -2752,19 +2799,19 @@ void _Make_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { } template -void make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // make [_First, _Last) into a heap, using _Pred +_CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // make [_First, _Last) into a heap, using _Pred _Adl_verify_range(_First, _Last); _Make_heap_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Pass_fn(_Pred)); } template -void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Last) into a heap, using operator< +_CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Last) into a heap, using operator< _STD make_heap(_First, _Last, less<>()); } // FUNCTION TEMPLATES is_heap AND is_heap_until template -_RanIt _Is_heap_until_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 _RanIt _Is_heap_until_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // find extent of range that is a heap ordered by _Pred using _Diff = _Iter_diff_t<_RanIt>; const _Diff _Size = _Last - _First; @@ -2778,7 +2825,7 @@ _RanIt _Is_heap_until_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { } template -_NODISCARD _RanIt is_heap_until(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _RanIt is_heap_until(_RanIt _First, _RanIt _Last, _Pr _Pred) { // find extent of range that is a heap ordered by _Pred _Adl_verify_range(_First, _Last); _Seek_wrapped(_First, _Is_heap_until_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Pass_fn(_Pred))); @@ -2786,7 +2833,8 @@ _NODISCARD _RanIt is_heap_until(_RanIt _First, _RanIt _Last, _Pr _Pred) { } template -_NODISCARD bool is_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // test if range is a heap ordered by _Pred +_NODISCARD _CONSTEXPR20 bool is_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // test if range is a heap ordered by _Pred _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -2794,13 +2842,13 @@ _NODISCARD bool is_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // test if ran } template -_NODISCARD _RanIt is_heap_until(_RanIt _First, _RanIt _Last) { +_NODISCARD _CONSTEXPR20 _RanIt is_heap_until(_RanIt _First, _RanIt _Last) { // find extent of range that is a heap ordered by operator< return _STD is_heap_until(_First, _Last, less<>()); } template -_NODISCARD bool is_heap(_RanIt _First, _RanIt _Last) { // test if range is a heap ordered by operator< +_NODISCARD _CONSTEXPR20 bool is_heap(_RanIt _First, _RanIt _Last) { // test if range is a heap ordered by operator< return _STD is_heap(_First, _Last, less<>()); } @@ -2829,14 +2877,15 @@ _NODISCARD bool is_heap(_ExPo&& _Exec, _RanIt _First, _RanIt _Last) noexcept /* // FUNCTION TEMPLATE sort_heap template -void _Sort_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order heap by repeatedly popping, using _Pred +_CONSTEXPR20 void _Sort_heap_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // order heap by repeatedly popping, using _Pred for (; 2 <= _Last - _First; --_Last) { _Pop_heap_unchecked(_First, _Last, _Pred); } } template -void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order heap by repeatedly popping, using _Pred +_CONSTEXPR20 void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order heap by repeatedly popping, using _Pred _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -2850,20 +2899,13 @@ void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order heap by repeat } template -void sort_heap(_RanIt _First, _RanIt _Last) { // order heap by repeatedly popping, using operator< +_CONSTEXPR20 void sort_heap(_RanIt _First, _RanIt _Last) { // order heap by repeatedly popping, using operator< _STD sort_heap(_First, _Last, less<>()); } -// FUNCTION TEMPLATE lower_bound -template -_NODISCARD _FwdIt lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { - // find first element not before _Val, using operator< - return _STD lower_bound(_First, _Last, _Val, less<>()); -} - // FUNCTION TEMPLATE upper_bound template -_NODISCARD _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // find first element that _Val is before, using _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -2885,14 +2927,14 @@ _NODISCARD _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr } template -_NODISCARD _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { +_NODISCARD _CONSTEXPR20 _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // find first element that _Val is before, using operator< return _STD upper_bound(_First, _Last, _Val, less<>()); } // FUNCTION TEMPLATE equal_range template -_NODISCARD pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // find range equivalent to _Val, using _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -2929,14 +2971,14 @@ _NODISCARD pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _ } template -_NODISCARD pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { +_NODISCARD _CONSTEXPR20 pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // find range equivalent to _Val, using operator< return _STD equal_range(_First, _Last, _Val, less<>()); } // FUNCTION TEMPLATE binary_search template -_NODISCARD bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // test if _Val equivalent to some element, using _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -2946,34 +2988,33 @@ _NODISCARD bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr } template -_NODISCARD bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { +_NODISCARD _CONSTEXPR20 bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // test if _Val equivalent to some element, using operator< return _STD binary_search(_First, _Last, _Val, less<>()); } // FUNCTION TEMPLATE merge -inline _Distance_unknown _Idl_dist_add(_Distance_unknown, _Distance_unknown) { - // combine _Idl_distance results (both unknown) +_NODISCARD constexpr _Distance_unknown _Idl_dist_add(_Distance_unknown, _Distance_unknown) { return {}; } template -_Distance_unknown _Idl_dist_add(_Diff1, _Distance_unknown) { // combine _Idl_distance results (right unknown) +_NODISCARD constexpr _Distance_unknown _Idl_dist_add(_Diff1, _Distance_unknown) { return {}; } template -_Distance_unknown _Idl_dist_add(_Distance_unknown, _Diff2) { // combine _Idl_distance results (left unknown) +_NODISCARD constexpr _Distance_unknown _Idl_dist_add(_Distance_unknown, _Diff2) { return {}; } template -auto _Idl_dist_add(_Diff1 _Lhs, _Diff2 _Rhs) { // combine _Idl_distance results (both known) +_NODISCARD constexpr auto _Idl_dist_add(_Diff1 _Lhs, _Diff2 _Rhs) { return _Lhs + _Rhs; } template -_OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { +_CONSTEXPR20_ICE _OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // copy merging ranges, both using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -3015,7 +3056,8 @@ _OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutI #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { +_CONSTEXPR20_ICE _DestTy* merge( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // copy merging ranges, both using _Pred, array dest return _STD merge(_First1, _Last1, _First2, _Last2, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Pred)) ._Unwrapped(); @@ -3023,14 +3065,15 @@ _DestTy* merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _De #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // copy merging ranges, both using operator< return _STD merge(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20_ICE _DestTy* merge( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { // copy merging ranges, both using operator<, array dest return _STD merge(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } @@ -3351,7 +3394,7 @@ void inplace_merge(_ExPo&&, _BidIt _First, _BidIt _Mid, _BidIt _Last) noexcept / // FUNCTION TEMPLATE sort template -_BidIt _Insertion_sort_unchecked(_BidIt _First, const _BidIt _Last, _Pr _Pred) { +_CONSTEXPR20_ICE _BidIt _Insertion_sort_unchecked(_BidIt _First, const _BidIt _Last, _Pr _Pred) { // insertion sort [_First, _Last), using _Pred if (_First != _Last) { for (_BidIt _Next = _First; ++_Next != _Last;) { // order next element @@ -3375,7 +3418,8 @@ _BidIt _Insertion_sort_unchecked(_BidIt _First, const _BidIt _Last, _Pr _Pred) { } template -void _Med3_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // sort median of three elements to middle +_CONSTEXPR20 void _Med3_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { + // sort median of three elements to middle if (_DEBUG_LT_PRED(_Pred, *_Mid, *_First)) { _STD iter_swap(_Mid, _First); } @@ -3390,7 +3434,8 @@ void _Med3_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // s } template -void _Guess_median_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // sort median element to middle +_CONSTEXPR20 void _Guess_median_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { + // sort median element to middle using _Diff = _Iter_diff_t<_RanIt>; const _Diff _Count = _Last - _First; if (40 < _Count) { // Tukey's ninther @@ -3406,7 +3451,7 @@ void _Guess_median_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred } template -pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { // partition [_First, _Last), using _Pred _RanIt _Mid = _First + ((_Last - _First) >> 1); // shift for codegen _Guess_median_unchecked(_First, _Mid, _Last - 1, _Pred); @@ -3473,9 +3518,9 @@ pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _First, _RanIt } template -void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) { +_CONSTEXPR20_ICE void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) { // order [_First, _Last), using _Pred - _Iter_diff_t<_RanIt> _Count; + _Iter_diff_t<_RanIt> _Count = 0; while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal) { // divide and conquer by quicksort auto _Mid = _Partition_by_median_guess_unchecked(_First, _Last, _Pred); @@ -3499,7 +3544,7 @@ void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _ } template -void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First, _Last), using _Pred +_CONSTEXPR20_ICE void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First, _Last), using _Pred _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -3507,7 +3552,7 @@ void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First } template -void sort(const _RanIt _First, const _RanIt _Last) { // order [_First, _Last), using operator< +_CONSTEXPR20_ICE void sort(const _RanIt _First, const _RanIt _Last) { // order [_First, _Last), using operator< _STD sort(_First, _Last, less<>()); } @@ -3722,7 +3767,7 @@ void stable_sort(_ExPo&& _Exec, _BidIt _First, _BidIt _Last) noexcept /* termina // FUNCTION TEMPLATE partial_sort template -void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // order [_First, _Last) up to _Mid, using _Pred _Adl_verify_range(_First, _Mid); _Adl_verify_range(_Mid, _Last); @@ -3746,7 +3791,8 @@ void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { } template -void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last) { // order [_First, _Last) up to _Mid, using operator< +_CONSTEXPR20 void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last) { + // order [_First, _Last) up to _Mid, using operator< _STD partial_sort(_First, _Mid, _Last, less<>()); } @@ -3768,7 +3814,7 @@ void partial_sort(_ExPo&&, _RanIt _First, _RanIt _Mid, _RanIt _Last) noexcept /* // FUNCTION TEMPLATE partial_sort_copy template -_RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2, _Pr _Pred) { +_CONSTEXPR20 _RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2, _Pr _Pred) { // copy [_First1, _Last1) into [_First2, _Last2) using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -3800,7 +3846,7 @@ _RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _La } template -_RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2) { +_CONSTEXPR20 _RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2) { // copy [_First1, _Last1) into [_First2, _Last2), using operator< return _STD partial_sort_copy(_First1, _Last1, _First2, _Last2, less<>()); } @@ -3827,7 +3873,8 @@ _RanIt partial_sort_copy( // FUNCTION TEMPLATE nth_element template -void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { // order Nth element, using _Pred +_CONSTEXPR20_ICE void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { + // order Nth element, using _Pred _Adl_verify_range(_First, _Nth); _Adl_verify_range(_Nth, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -3853,7 +3900,7 @@ void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { // order } template -void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last) { // order Nth element, using operator< +_CONSTEXPR20_ICE void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last) { // order Nth element, using operator< _STD nth_element(_First, _Nth, _Last, less<>()); } @@ -3875,7 +3922,7 @@ void nth_element(_ExPo&&, _RanIt _First, _RanIt _Nth, _RanIt _Last) noexcept /* // FUNCTION TEMPLATE includes template -_NODISCARD bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { // test if every element in sorted [_First2, _Last2) is in sorted [_First1, _Last1), using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -3899,7 +3946,7 @@ _NODISCARD bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _ } template -_NODISCARD bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { +_NODISCARD _CONSTEXPR20 bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { // test if every element in sorted [_First2, _Last2) is in sorted [_First1, _Last1), using operator< return _STD includes(_First1, _Last1, _First2, _Last2, less<>()); } @@ -3929,7 +3976,8 @@ _NODISCARD bool includes( // FUNCTION TEMPLATE set_union template -_OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { +_CONSTEXPR20_ICE _OutIt set_union( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // OR sets [_First1, _Last1) and [_First2, _Last2), using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -3961,7 +4009,7 @@ _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _ #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_union( +_CONSTEXPR20_ICE _DestTy* set_union( _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // OR sets [_First1, _Last1) and [_First2, _Last2), array dest return _STD set_union(_First1, _Last1, _First2, _Last2, _Array_iterator<_DestTy, _DestSize>(_Dest), _Pass_fn(_Pred)) @@ -3970,14 +4018,15 @@ _DestTy* set_union( #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // OR sets [_First1, _Last1) and [_First2, _Last2), using operator< return _STD set_union(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20_ICE _DestTy* set_union( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { // OR sets [_First1, _Last1) and [_First2, _Last2), array dest return _STD set_union(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } @@ -4035,7 +4084,8 @@ _DestTy* set_union(_ExPo&&, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _F // FUNCTION TEMPLATE set_intersection template -_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { +_CONSTEXPR20 _OutIt set_intersection( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // AND sets [_First1, _Last1) and [_First2, _Last2), using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -4065,7 +4115,7 @@ _OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _L #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_intersection( +_CONSTEXPR20 _DestTy* set_intersection( _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // AND sets [_First1, _Last1) and [_First2, _Last2), array dest return _STD set_intersection( @@ -4075,14 +4125,15 @@ _DestTy* set_intersection( #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { +_CONSTEXPR20 _OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // AND sets [_First1, _Last1) and [_First2, _Last2), using operator< return _STD set_intersection(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20 _DestTy* set_intersection( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { // AND sets [_First1, _Last1) and [_First2, _Last2), array dest return _STD set_intersection(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } @@ -4125,7 +4176,8 @@ _DestTy* set_intersection(_ExPo&& _Exec, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt // FUNCTION TEMPLATE set_difference template -_OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { +_CONSTEXPR20_ICE _OutIt set_difference( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // take set [_First2, _Last2) from [_First1, _Last1), using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -4156,7 +4208,7 @@ _OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Las #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_difference( +_CONSTEXPR20_ICE _DestTy* set_difference( _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // take set [_First2, _Last2) from [_First1, _Last1), array dest return _STD set_difference( @@ -4166,14 +4218,15 @@ _DestTy* set_difference( #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // take set [_First2, _Last2) from [_First1, _Last1), using operator< return _STD set_difference(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20_ICE _DestTy* set_difference( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { // take set [_First2, _Last2) from [_First1, _Last1), array dest return _STD set_difference(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } @@ -4216,7 +4269,8 @@ _DestTy* set_difference(_ExPo&& _Exec, _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 // FUNCTION TEMPLATE set_symmetric_difference template -_OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { +_CONSTEXPR20_ICE _OutIt set_symmetric_difference( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // XOR sets [_First1, _Last1) and [_First2, _Last2), using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -4249,7 +4303,7 @@ _OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _ #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_symmetric_difference( +_CONSTEXPR20_ICE _DestTy* set_symmetric_difference( _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred) { // XOR sets [_First1, _Last1) and [_First2, _Last2), array dest return _STD set_symmetric_difference( @@ -4259,14 +4313,15 @@ _DestTy* set_symmetric_difference( #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt set_symmetric_difference( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // XOR sets [_First1, _Last1) and [_First2, _Last2), using operator< return _STD set_symmetric_difference(_First1, _Last1, _First2, _Last2, _Dest, less<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* set_symmetric_difference( +_CONSTEXPR20_ICE _DestTy* set_symmetric_difference( _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]) { // XOR sets [_First1, _Last1) and [_First2, _Last2), array dest return _STD set_symmetric_difference(_First1, _Last1, _First2, _Last2, _Dest, less<>()); @@ -4592,7 +4647,8 @@ _NODISCARD constexpr pair<_Ty, _Ty> minmax(initializer_list<_Ty> _Ilist) { // FUNCTION TEMPLATE next_permutation template -bool next_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { // permute and test for pure ascending, using _Pred +_CONSTEXPR20 bool next_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { + // permute and test for pure ascending, using _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4622,13 +4678,14 @@ bool next_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { // permute and t } template -bool next_permutation(_BidIt _First, _BidIt _Last) { // permute and test for pure ascending, using operator< +_CONSTEXPR20 bool next_permutation(_BidIt _First, _BidIt _Last) { + // permute and test for pure ascending, using operator< return _STD next_permutation(_First, _Last, less<>()); } // FUNCTION TEMPLATE prev_permutation template -bool prev_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { +_CONSTEXPR20 bool prev_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { // reverse permute and test for pure descending, using _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -4659,13 +4716,14 @@ bool prev_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { } template -bool prev_permutation(_BidIt _First, _BidIt _Last) { // reverse permute and test for pure descending, using operator< +_CONSTEXPR20 bool prev_permutation(_BidIt _First, _BidIt _Last) { + // reverse permute and test for pure descending, using operator< return _STD prev_permutation(_First, _Last, less<>()); } // FUNCTION TEMPLATES is_sorted AND is_sorted_until template -_NODISCARD _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find extent of range that is ordered by predicate _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -4684,7 +4742,8 @@ _NODISCARD _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) } template -_NODISCARD bool is_sorted(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // test if range is ordered by predicate +_NODISCARD _CONSTEXPR20 bool is_sorted(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { + // test if range is ordered by predicate _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4692,12 +4751,13 @@ _NODISCARD bool is_sorted(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // test if r } template -_NODISCARD _FwdIt is_sorted_until(_FwdIt _First, _FwdIt _Last) { // find extent of range that is ordered by operator< +_NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(_FwdIt _First, _FwdIt _Last) { + // find extent of range that is ordered by operator< return _STD is_sorted_until(_First, _Last, less<>()); } template -_NODISCARD bool is_sorted(_FwdIt _First, _FwdIt _Last) { // test if range is ordered by operator< +_NODISCARD _CONSTEXPR20 bool is_sorted(_FwdIt _First, _FwdIt _Last) { // test if range is ordered by operator< return _STD is_sorted(_First, _Last, less<>()); } diff --git a/stl/inc/numeric b/stl/inc/numeric index 7035c7e65f3..c22b937d5ce 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -75,26 +75,21 @@ _NODISCARD _CONSTEXPR20_ICE _Ty reduce(const _InIt _First, const _InIt _Last, _T _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); + if constexpr (_Plus_on_arithmetic_ranges_reduction_v<_Unwrapped_t, _Ty, _BinOp>) { #ifdef __cpp_lib_is_constant_evaluated - // TRANSITION, DevCom-878972 - if (_STD is_constant_evaluated()) { - for (; _UFirst != _ULast; ++_UFirst) { - _Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713 - } - return _Val; - } else -#endif // __cpp_lib_is_constant_evaluated - { - if constexpr (_Plus_on_arithmetic_ranges_reduction_v<_Unwrapped_t, _Ty, _BinOp>) { + if (!_STD is_constant_evaluated()) +#endif + { (void) _Reduce_op; // TRANSITION, VSO-486357 return _Reduce_plus_arithmetic_ranges(_UFirst, _ULast, _Val); - } else { - for (; _UFirst != _ULast; ++_UFirst) { - _Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713 - } - return _Val; } } + + for (; _UFirst != _ULast; ++_UFirst) { + _Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713 + } + + return _Val; } template @@ -211,29 +206,23 @@ _NODISCARD _CONSTEXPR20_ICE _Ty transform_reduce( auto _UFirst1 = _Get_unwrapped(_First1); const auto _ULast1 = _Get_unwrapped(_Last1); auto _UFirst2 = _Get_unwrapped_n(_First2, _Idl_distance<_InIt1>(_UFirst1, _ULast1)); + if constexpr (_Default_ops_transform_reduce_v<_Unwrapped_t, _Unwrapped_t, _Ty, + _BinOp1, _BinOp2>) { #ifdef __cpp_lib_is_constant_evaluated - // TRANSITION, DevCom-878972 - if (_STD is_constant_evaluated()) { - for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) { - _Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4713 - } - return _Val; - } else + // TRANSITION, DevCom-878972 + if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated - { - if constexpr (_Default_ops_transform_reduce_v<_Unwrapped_t, _Unwrapped_t, _Ty, - _BinOp1, _BinOp2>) { + { (void) _Reduce_op; // TRANSITION, VSO-486357 (void) _Transform_op; // TRANSITION, VSO-486357 return _Transform_reduce_arithmetic_defaults(_UFirst1, _ULast1, _UFirst2, _STD move(_Val)); - } else { - for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) { - _Val = - _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4713 - } - return _Val; } } + + for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) { + _Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4713 + } + return _Val; } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS diff --git a/stl/inc/type_traits b/stl/inc/type_traits index 93d59e1559d..0826981d501 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -1949,10 +1949,10 @@ template && is_move_assigna #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv template #endif // _HAS_CXX17 -void swap(_Ty&, _Ty&) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>); +_CONSTEXPR20 void swap(_Ty&, _Ty&) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>); template ::value, int> = 0> -void swap(_Ty (&)[_Size], _Ty (&)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value); +_CONSTEXPR20 void swap(_Ty (&)[_Size], _Ty (&)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value); // STRUCT TEMPLATE _Swappable_with_helper template diff --git a/stl/inc/utility b/stl/inc/utility index 876ec0353c4..70bf9094009 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -39,13 +39,13 @@ _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty& _Max_value // FUNCTION TEMPLATE iter_swap (from ) template -void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right +_CONSTEXPR20 void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right swap(*_Left, *_Right); } // FUNCTION TEMPLATE swap template ::value, int> _Enabled> -void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value) { +_CONSTEXPR20 void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value) { if (&_Left != &_Right) { _Ty* _First1 = _Left; _Ty* _Last1 = _First1 + _Size; @@ -61,7 +61,8 @@ template && is_move_assigna #else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv template #endif // _HAS_CXX17 -void swap(_Ty& _Left, _Ty& _Right) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) { +_CONSTEXPR20 void swap(_Ty& _Left, _Ty& _Right) noexcept( + is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) { _Ty _Tmp = _STD move(_Left); _Left = _STD move(_Right); _Right = _STD move(_Tmp); @@ -69,7 +70,7 @@ void swap(_Ty& _Left, _Ty& _Right) noexcept(is_nothrow_move_constructible_v<_Ty> // FUNCTION TEMPLATE _Swap_adl template -void _Swap_adl(_Ty& _Left, _Ty& _Right) noexcept(_Is_nothrow_swappable<_Ty>::value) { +_CONSTEXPR20 void _Swap_adl(_Ty& _Left, _Ty& _Right) noexcept(_Is_nothrow_swappable<_Ty>::value) { swap(_Left, _Right); } @@ -566,7 +567,7 @@ _NODISCARD constexpr const _Ty2&& get( // FUNCTION TEMPLATE exchange template -_Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept( +_CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept( conjunction_v, is_nothrow_assignable<_Ty&, _Other>>) /* strengthened */ { // assign _New_val to _Val, return previous _Val _Ty _Old_val = static_cast<_Ty&&>(_Val); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index e2065d559f9..8fe7667678d 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1997,7 +1997,8 @@ struct _Alloc_temporary { // FUNCTION TEMPLATE remove template -_NODISCARD _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { // remove each matching _Val +_NODISCARD _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { + // remove each matching _Val _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -2018,7 +2019,8 @@ _NODISCARD _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { / // FUNCTION TEMPLATE remove_if template -_NODISCARD _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred +_NODISCARD _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { + // remove each satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); diff --git a/stl/inc/xutility b/stl/inc/xutility index 8fbe63e5bee..c329ecee9b2 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1377,78 +1377,6 @@ struct _Unwrap_enum<_Elem, false> { // passthrough non-enum type template using _Unwrap_enum_t = typename _Unwrap_enum<_Elem>::type; -// ALGORITHM DISPATCH TRAITS -template -class move_iterator; - -template -struct _Ptr_cat_helper { // determines _Ptr_cat's result in the most general case - using _USource = _Unwrap_enum_t<_Source>; - using _UDest = _Unwrap_enum_t<_Dest>; - static constexpr bool _Really_trivial = conjunction_v< - bool_constant == is_same_v>, - is_integral<_USource>, is_integral<_UDest>>; - static constexpr bool _Trivially_copyable = _Really_trivial; -}; - -template -struct _Ptr_cat_helper<_Elem, _Elem> { // determines _Ptr_cat's result when the types are the same - static constexpr bool _Really_trivial = is_trivial_v<_Elem>; - static constexpr bool _Trivially_copyable = is_trivially_copyable_v<_Elem>; -}; - -template -struct _Ptr_cat_helper<_Anything*, const _Anything*> { - // determines _Ptr_cat's result when all we do is add const to a pointer - static constexpr bool _Really_trivial = true; - static constexpr bool _Trivially_copyable = true; -}; - -template -struct _Ptr_cat_helper<_Anything*, volatile _Anything*> { - // determines _Ptr_cat's result when all we do is add volatile to a pointer - static constexpr bool _Really_trivial = true; - static constexpr bool _Trivially_copyable = true; -}; - -template -struct _Ptr_cat_helper<_Anything*, const volatile _Anything*> { - // determines _Ptr_cat's result when all we do is add cv to a pointer - static constexpr bool _Really_trivial = true; - static constexpr bool _Trivially_copyable = true; -}; - -struct _False_copy_cat { - static constexpr bool _Really_trivial = false; - static constexpr bool _Trivially_copyable = false; -}; - -template -struct _Ptr_copy_cat : _False_copy_cat {}; // return pointer copy optimization category for arbitrary iterators - -template -struct _Ptr_copy_cat<_Source*, _Dest*> - : conditional_t, - _Ptr_cat_helper, remove_cv_t<_Dest>>, _False_copy_cat> { -}; // return pointer copy optimization category for pointers - -template -struct _Ptr_copy_cat, _Dest*> : _Ptr_copy_cat<_Source*, _Dest*> { -}; // return pointer copy optimization category for move iterators - -template -struct _Ptr_move_cat : _False_copy_cat {}; // return pointer move optimization category for arbitrary iterators - -template -struct _Ptr_move_cat<_Source*, _Dest*> - : conditional_t, - _Ptr_cat_helper, remove_cv_t<_Dest>>, _False_copy_cat> { -}; // return pointer move optimization category for pointers - -template -struct _Ptr_move_cat, _Dest*> : _Ptr_move_cat<_Source*, _Dest*> { -}; // return pointer move optimization category for move iterators - // DEBUG TESTING MACROS #if _ITERATOR_DEBUG_LEVEL < 2 @@ -1486,7 +1414,7 @@ constexpr bool _Debug_lt_pred(_Pr&& _Pred, _Ty1&& _Left, _Ty2&& _Right) noexcept // FUNCTION TEMPLATE _Debug_order_unchecked #if _HAS_IF_CONSTEXPR template -void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred) { +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 (_First != _Last) { @@ -1502,12 +1430,12 @@ void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred) { } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template -void _Debug_order_unchecked2(_InIt, _Sentinel, _Pr&, input_iterator_tag) { +constexpr void _Debug_order_unchecked2(_InIt, _Sentinel, _Pr&, input_iterator_tag) { // (don't) test if range is ordered by predicate, input iterators } template -void _Debug_order_unchecked2(_FwdIt _First, _Sentinel _Last, _Pr& _Pred, forward_iterator_tag) { +constexpr void _Debug_order_unchecked2(_FwdIt _First, _Sentinel _Last, _Pr& _Pred, forward_iterator_tag) { // test if range is ordered by predicate, forward iterators if (_First != _Last) { for (_FwdIt _Next = _First; ++_Next != _Last; _First = _Next) { @@ -1517,7 +1445,7 @@ void _Debug_order_unchecked2(_FwdIt _First, _Sentinel _Last, _Pr& _Pred, forward } template -void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred) { +constexpr void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred) { // test if range is ordered by predicate _Debug_order_unchecked2(_First, _Last, _Pred, _Iter_cat_t<_InIt>()); } @@ -1526,7 +1454,7 @@ void _Debug_order_unchecked(_InIt _First, _Sentinel _Last, _Pr&& _Pred) { // FUNCTION TEMPLATE _Debug_order_set_unchecked #if _HAS_IF_CONSTEXPR template -void _Debug_order_set_unchecked(_InIt _First, _InIt _Last, _Pr&& _Pred) { +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>) { _Debug_order_unchecked(_First, _Last, _Pred); @@ -1551,13 +1479,14 @@ void _Debug_order_set_unchecked2(_InIt, _InIt, _Pr&, input_iterator_tag, } template -void _Debug_order_set_unchecked2(_FwdIt _First, _FwdIt _Last, _Pr& _Pred, forward_iterator_tag, _Priority_tag<1>) { +constexpr void _Debug_order_set_unchecked2( + _FwdIt _First, _FwdIt _Last, _Pr& _Pred, forward_iterator_tag, _Priority_tag<1>) { // test if range is ordered by predicate, forward iterators and same types _Debug_order_unchecked2(_First, _Last, _Pred, forward_iterator_tag{}); } template -void _Debug_order_set_unchecked(_InIt _First, _InIt _Last, _Pr&& _Pred) { +constexpr void _Debug_order_set_unchecked(_InIt _First, _InIt _Last, _Pr&& _Pred) { // test if range is ordered by predicate _Debug_order_set_unchecked2(_First, _Last, _Pred, _Iter_cat_t<_InIt>(), _Priority_tag, _Iter_value_t<_InIt>>>()); @@ -3569,8 +3498,72 @@ inline constexpr unreachable_sentinel_t unreachable_sentinel{}; #endif // __cpp_lib_concepts // FUNCTION TEMPLATE copy +template +struct _Ptr_cat_helper { + using _USource = _Unwrap_enum_t<_Source>; + using _UDest = _Unwrap_enum_t<_Dest>; + static constexpr bool _Really_trivial = conjunction_v< + bool_constant == is_same_v>, + is_integral<_USource>, is_integral<_UDest>>; + static constexpr bool _Trivially_copyable = _Really_trivial; +}; + +template +struct _Ptr_cat_helper<_Elem, _Elem> { // determines _Ptr_cat's result when the types are the same + static constexpr bool _Really_trivial = is_trivial_v<_Elem>; + static constexpr bool _Trivially_copyable = is_trivially_copyable_v<_Elem>; +}; + +template +struct _Ptr_cat_helper<_Anything*, const _Anything*> { + // determines _Ptr_cat's result when all we do is add const to a pointer + static constexpr bool _Really_trivial = true; + static constexpr bool _Trivially_copyable = true; +}; + +template +struct _Ptr_cat_helper<_Anything*, volatile _Anything*> { + // determines _Ptr_cat's result when all we do is add volatile to a pointer + static constexpr bool _Really_trivial = true; + static constexpr bool _Trivially_copyable = true; +}; + +template +struct _Ptr_cat_helper<_Anything*, const volatile _Anything*> { + // determines _Ptr_cat's result when all we do is add cv to a pointer + static constexpr bool _Really_trivial = true; + static constexpr bool _Trivially_copyable = true; +}; + +struct _False_copy_cat { + static constexpr bool _Really_trivial = false; + static constexpr bool _Trivially_copyable = false; +}; + +template +struct _Ptr_copy_cat : _False_copy_cat {}; // unwrap the pointer-like type and dispatch to _Ptr_cat_helper for copy + +template +struct _Ptr_copy_cat<_Source*, _Dest*> + : conditional_t, + _Ptr_cat_helper, remove_cv_t<_Dest>>, _False_copy_cat> {}; + +template +struct _Ptr_copy_cat, _Dest*> : _Ptr_copy_cat<_Source*, _Dest*> {}; + +template +struct _Ptr_move_cat : _False_copy_cat {}; // unwrap the pointer-like type and dispatch to _Ptr_cat_helper for move + +template +struct _Ptr_move_cat<_Source*, _Dest*> + : conditional_t, + _Ptr_cat_helper, remove_cv_t<_Dest>>, _False_copy_cat> {}; + +template +struct _Ptr_move_cat, _Dest*> : _Ptr_move_cat<_Source*, _Dest*> {}; + template -_OutIt _Copy_memmove(_InIt _First, _InIt _Last, _OutIt _Dest) { // implement copy-like function as memmove +_OutIt _Copy_memmove(_InIt _First, _InIt _Last, _OutIt _Dest) { const char* const _First_ch = const_cast(reinterpret_cast(_First)); const char* const _Last_ch = const_cast(reinterpret_cast(_Last)); char* const _Dest_ch = const_cast(reinterpret_cast(_Dest)); @@ -3586,18 +3579,23 @@ _OutIt _Copy_memmove(move_iterator<_InIt> _First, move_iterator<_InIt> _Last, _O #if _HAS_IF_CONSTEXPR template -_OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) - // note: _Copy_unchecked is called directly from elsewhere in the STL + // note: _Copy_unchecked has callers other than the copy family if constexpr (_Ptr_copy_cat<_InIt, _OutIt>::_Trivially_copyable) { - return _Copy_memmove(_First, _Last, _Dest); - } else { - for (; _First != _Last; ++_Dest, (void) ++_First) { - *_Dest = *_First; +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Copy_memmove(_First, _Last, _Dest); } + } - return _Dest; + for (; _First != _Last; ++_Dest, (void) ++_First) { + *_Dest = *_First; } + + return _Dest; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template @@ -3619,13 +3617,13 @@ _OutIt _Copy_unchecked1(_InIt _First, _InIt _Last, _OutIt _Dest, true_type) { template _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) - // note: _Copy_unchecked is called directly from elsewhere in the STL + // note: _Copy_unchecked has callers other than the copy family return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Ptr_copy_cat<_InIt, _OutIt>::_Trivially_copyable>{}); } #endif // _HAS_IF_CONSTEXPR template -_OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) +_CONSTEXPR20_ICE _OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -3636,7 +3634,8 @@ _OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) t #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_DestTy* copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize]) { // copy [_First, _Last) to [_Dest, ...) +_CONSTEXPR20_ICE _DestTy* copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize]) { + // copy [_First, _Last) to [_Dest, ...) return _STD copy(_First, _Last, _Array_iterator<_DestTy, _DestSize>(_Dest))._Unwrapped(); } #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS @@ -3665,25 +3664,33 @@ _DestTy* copy(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _DestTy (&_Dest)[_DestSize // FUNCTION TEMPLATE copy_n #if _HAS_IF_CONSTEXPR template -_OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _First + _Count) to [_Dest, ...) +_CONSTEXPR20_ICE _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { + // copy [_First, _First + _Count) to [_Dest, ...) _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); if constexpr (_Ptr_copy_cat::_Trivially_copyable) { - _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); - } else { - for (;;) { - *_UDest = *_UFirst; - ++_UDest; - --_Count; - if (_Count == 0) { // note that we avoid an extra ++_First here to allow istream_iterator to work, - // see LWG-2471 - break; - } +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); + _Seek_wrapped(_Dest, _UDest); + return _Dest; + } + } - ++_UFirst; + for (;;) { + *_UDest = *_UFirst; + ++_UDest; + --_Count; + if (_Count == 0) { // note that we avoid an extra ++_First here to allow istream_iterator to work, + // see LWG-2471 + break; } + + ++_UFirst; } _Seek_wrapped(_Dest, _UDest); @@ -3734,7 +3741,7 @@ _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _ #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_OutIt copy_n(_SourceTy (&_First)[_SourceSize], _Diff _Count_raw, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt copy_n(_SourceTy (&_First)[_SourceSize], _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _First + _Count) to [_Dest, ...), array source const _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { @@ -3746,7 +3753,7 @@ _OutIt copy_n(_SourceTy (&_First)[_SourceSize], _Diff _Count_raw, _OutIt _Dest) } template -_DestTy* copy_n(_InIt _First, _Diff _Count_raw, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20_ICE _DestTy* copy_n(_InIt _First, _Diff _Count_raw, _DestTy (&_Dest)[_DestSize]) { // copy [_First, _First + _Count) to [_Dest, ...), array dest const _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { @@ -3758,7 +3765,7 @@ _DestTy* copy_n(_InIt _First, _Diff _Count_raw, _DestTy (&_Dest)[_DestSize]) { } template -_DestTy* copy_n(_SourceTy (&_First)[_SourceSize], _Diff _Count_raw, _DestTy (&_Dest)[_DestSize]) { +_CONSTEXPR20_ICE _DestTy* copy_n(_SourceTy (&_First)[_SourceSize], _Diff _Count_raw, _DestTy (&_Dest)[_DestSize]) { // copy [_First, _First + _Count) to [_Dest, ...), array source/dest const _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { @@ -3829,20 +3836,26 @@ _BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_Bid #if _HAS_IF_CONSTEXPR template -_BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { +_CONSTEXPR20_ICE _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_First, _Last) backwards to [..., _Dest) _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast)); if constexpr (_Ptr_copy_cat::_Trivially_copyable) { - _UDest = _Copy_backward_memmove(_UFirst, _ULast, _UDest); - } else { - while (_UFirst != _ULast) { - *--_UDest = *--_ULast; +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _UDest = _Copy_backward_memmove(_UFirst, _ULast, _UDest); + _Seek_wrapped(_Dest, _UDest); + return _Dest; } } + while (_UFirst != _ULast) { + *--_UDest = *--_ULast; + } _Seek_wrapped(_Dest, _UDest); return _Dest; } @@ -3887,18 +3900,23 @@ _BidIt2 copy_backward(_ExPo&&, _BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) noe // FUNCTION TEMPLATE move #if _HAS_IF_CONSTEXPR template -_OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...) - // note: _Move_unchecked is called directly from elsewhere in the STL + // note: _Move_unchecked has callers other than the move family if constexpr (_Ptr_move_cat<_InIt, _OutIt>::_Trivially_copyable) { - return _Copy_memmove(_First, _Last, _Dest); - } else { - for (; _First != _Last; ++_Dest, (void) ++_First) { - *_Dest = _STD move(*_First); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Copy_memmove(_First, _Last, _Dest); } + } - return _Dest; + for (; _First != _Last; ++_Dest, (void) ++_First) { + *_Dest = _STD move(*_First); } + + return _Dest; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template @@ -3920,13 +3938,13 @@ _OutIt _Move_unchecked1(_InIt _First, _InIt _Last, _OutIt _Dest, true_type) { template _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...), choose optimization - // note: _Move_unchecked is called directly from elsewhere in the STL + // note: _Move_unchecked has callers other than the move family return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Ptr_move_cat<_InIt, _OutIt>::_Trivially_copyable>{}); } #endif // _HAS_IF_CONSTEXPR template -_OutIt move(_InIt _First, _InIt _Last, _OutIt _Dest) { +_CONSTEXPR20_ICE _OutIt move(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...) _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); @@ -3967,18 +3985,23 @@ _DestTy* move(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _DestTy (&_Dest)[_DestSize // FUNCTION TEMPLATE move_backward #if _HAS_IF_CONSTEXPR template -_BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { +_CONSTEXPR20_ICE _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest) - // note: _Move_backward_unchecked is called directly from elsewhere in the STL + // note: _Move_backward_unchecked has callers other than the move_backward family if constexpr (_Ptr_move_cat<_BidIt1, _BidIt2>::_Trivially_copyable) { - return _Copy_backward_memmove(_First, _Last, _Dest); - } else { - while (_First != _Last) { - *--_Dest = _STD move(*--_Last); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Copy_backward_memmove(_First, _Last, _Dest); } + } - return _Dest; + while (_First != _Last) { + *--_Dest = _STD move(*--_Last); } + + return _Dest; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template @@ -4000,14 +4023,15 @@ _BidIt2 _Move_backward_unchecked1(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest, template _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest), choose optimization - // note: _Move_backward_unchecked is called directly from elsewhere in the STL + // note: _Move_backward_unchecked has callers other than the move_backward family return _Move_backward_unchecked1( _First, _Last, _Dest, bool_constant<_Ptr_move_cat<_BidIt1, _BidIt2>::_Trivially_copyable>{}); } #endif // _HAS_IF_CONSTEXPR template -_BidIt2 move_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest) +_CONSTEXPR20_ICE _BidIt2 move_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { + // move [_First, _Last) backwards to [..., _Dest) _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -4067,17 +4091,24 @@ _INLINE_VAR constexpr bool _Fill_memset_is_safe<_FwdIt, _Ty, false> = false; #if _HAS_IF_CONSTEXPR template -void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { // copy _Val through [_First, _Last) +_CONSTEXPR20_ICE void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { + // copy _Val through [_First, _Last) _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); if constexpr (_Fill_memset_is_safe) { - _CSTD memset(_UFirst, static_cast(_Val), static_cast(_ULast - _UFirst)); - } else { - for (; _UFirst != _ULast; ++_UFirst) { - *_UFirst = _Val; +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _CSTD memset(_UFirst, static_cast(_Val), static_cast(_ULast - _UFirst)); + return; } } + + for (; _UFirst != _ULast; ++_UFirst) { + *_UFirst = _Val; + } } #else // ^^^ _HAS_IF_CONSTEXPR // !_HAS_IF_CONSTEXPR vvv template @@ -4115,20 +4146,27 @@ void fill(_ExPo&&, _FwdIt _First, _FwdIt _Last, const _Ty& _Val) noexcept /* ter // FUNCTION TEMPLATE fill_n #if _HAS_IF_CONSTEXPR template -_OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val) { +_CONSTEXPR20_ICE _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val) { // copy _Val _Count times through [_Dest, ...) _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { auto _UDest = _Get_unwrapped_n(_Dest, _Count); if constexpr (_Fill_memset_is_safe) { - _CSTD memset(_UDest, static_cast(_Val), static_cast(_Count)); - _UDest += _Count; - } else { - for (; 0 < _Count; --_Count, (void) ++_UDest) { - *_UDest = _Val; +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _CSTD memset(_UDest, static_cast(_Val), static_cast(_Count)); + _UDest += _Count; + _Seek_wrapped(_Dest, _UDest); + return _Dest; } } + for (; 0 < _Count; --_Count, (void) ++_UDest) { + *_UDest = _Val; + } + _Seek_wrapped(_Dest, _UDest); } @@ -4230,26 +4268,31 @@ typename _Equal_memcmp_is_safe_helper, remove_const_t<_Obj #if _HAS_IF_CONSTEXPR template -_NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20_ICE bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Pr _Pred) { // compare [_First1, _Last1) to [_First2, ...) using _Pred _Adl_verify_range(_First1, _Last1); auto _UFirst1 = _Get_unwrapped(_First1); const auto _ULast1 = _Get_unwrapped(_Last1); auto _UFirst2 = _Get_unwrapped_n(_First2, _Idl_distance<_InIt1>(_UFirst1, _ULast1)); if constexpr (decltype(_Equal_memcmp_is_safe(_UFirst1, _UFirst2, _Pred))::value) { - const auto _First1_ch = reinterpret_cast(_UFirst1); - const auto _First2_ch = reinterpret_cast(_UFirst2); - const auto _Count = static_cast(reinterpret_cast(_ULast1) - _First1_ch); - return _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0; - } else { - for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) { - if (!_Pred(*_UFirst1, *_UFirst2)) { - return false; - } +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _First1_ch = reinterpret_cast(_UFirst1); + const auto _First2_ch = reinterpret_cast(_UFirst2); + const auto _Count = static_cast(reinterpret_cast(_ULast1) - _First1_ch); + return _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0; } + } - return true; + for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) { + if (!_Pred(*_UFirst1, *_UFirst2)) { + return false; + } } + + return true; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template @@ -4292,7 +4335,8 @@ _NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _F #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template , int> = 0> -_NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], _Pr _Pred) { +_NODISCARD _CONSTEXPR20_ICE bool equal( + const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], _Pr _Pred) { // compare [_First1, _Last1) to [_First2, ...) using _Pred return _STD equal(_First1, _Last1, _Array_iterator<_RightTy, _RightSize>(_First2), _Pass_fn(_Pred)); } @@ -4318,14 +4362,14 @@ _NODISCARD bool equal(_ExPo&& _Exec, _FwdIt1 _First1, _FwdIt1 _Last1, _RightTy ( #endif // _HAS_CXX17 template -_NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2) { +_NODISCARD _CONSTEXPR20_ICE bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2) { // compare [_First1, _Last1) to [_First2, ...) return _STD equal(_First1, _Last1, _First2, equal_to<>()); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize]) { +_NODISCARD _CONSTEXPR20_ICE bool equal(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize]) { // compare [_First1, _Last1) to [_First2, ...) return _STD equal(_First1, _Last1, _First2, equal_to<>()); } @@ -4351,7 +4395,8 @@ _NODISCARD bool equal(_ExPo&& _Exec, const _FwdIt1 _First1, const _FwdIt1 _Last1 #if _HAS_IF_CONSTEXPR template -_NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20_ICE bool equal( + const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { // compare [_First1, _Last1) to [_First2, _Last2) using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -4435,7 +4480,8 @@ _NODISCARD bool equal(_ExPo&& _Exec, const _FwdIt1 _First1, const _FwdIt1 _Last1 #endif // _HAS_CXX17 template -_NODISCARD bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, const _InIt2 _Last2) { +_NODISCARD _CONSTEXPR20_ICE bool equal( + const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, const _InIt2 _Last2) { // compare [_First1, _Last1) to [_First2, _Last2) return _STD equal(_First1, _Last1, _First2, _Last2, equal_to<>()); } @@ -4485,27 +4531,27 @@ using _Lex_compare_check_element_types = _Lex_compare_optimize>; // checks the lex_compare element types for memcmp safety template -_Lex_compare_optimize _Lex_compare_memcmp_classify(const _InIt1&, const _InIt2&, const _Pr&) { +constexpr _Lex_compare_optimize _Lex_compare_memcmp_classify(const _InIt1&, const _InIt2&, const _Pr&) { // return lex_compare optimization category for arbitrary iterators return {}; } template -_Lex_compare_check_element_types, _Obj1, _Obj2, _FTy> _Lex_compare_memcmp_classify( +constexpr _Lex_compare_check_element_types, _Obj1, _Obj2, _FTy> _Lex_compare_memcmp_classify( _Obj1* const&, _Obj2* const&, const less<_FTy>&) { // return lex_compare optimization category for pointer iterators and less<_FTy> return {}; } template -_Lex_compare_check_element_types, _Obj1, _Obj2, _FTy> _Lex_compare_memcmp_classify( +constexpr _Lex_compare_check_element_types, _Obj1, _Obj2, _FTy> _Lex_compare_memcmp_classify( _Obj1* const&, _Obj2* const&, const greater<_FTy>&) { // return lex_compare optimization category for pointer iterators and greater<_FTy> return {}; } template -bool _Lex_compare_unchecked( +_NODISCARD constexpr bool _Lex_compare_unchecked( _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred, _Lex_compare_optimize) { // order [_First1, _Last1) vs. [_First2, _Last2) using _Pred, no special optimization for (; _First1 != _Last1 && _First2 != _Last2; ++_First1, (void) ++_First2) { // something to compare, do it @@ -4520,9 +4566,15 @@ bool _Lex_compare_unchecked( } template -bool _Lex_compare_unchecked( - _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr, _Lex_compare_optimize<_Memcmp_pr>) { +_NODISCARD _CONSTEXPR20_ICE bool _Lex_compare_unchecked( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred, _Lex_compare_optimize<_Memcmp_pr>) { // order [_First1, _Last1) vs. [_First2, _Last2) memcmp optimization +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + return _Lex_compare_unchecked(_First1, _Last1, _First2, _Last2, _Pred, _Lex_compare_optimize{}); + } +#endif // __cpp_lib_is_constant_evaluated + (void) _Pred; const auto _Num1 = static_cast(_Last1 - _First1); const auto _Num2 = static_cast(_Last2 - _First2); const int _Ans = _CSTD memcmp(_First1, _First2, _Num1 < _Num2 ? _Num1 : _Num2); @@ -4530,7 +4582,8 @@ bool _Lex_compare_unchecked( } template -_NODISCARD bool lexicographical_compare(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20_ICE bool lexicographical_compare( + _InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { // order [_First1, _Last1) vs. [_First2, _Last2) using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -4543,7 +4596,7 @@ _NODISCARD bool lexicographical_compare(_InIt1 _First1, _InIt1 _Last1, _InIt2 _F } template -_NODISCARD bool lexicographical_compare(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { +_NODISCARD _CONSTEXPR20_ICE bool lexicographical_compare(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { // order [_First1, _Last1) vs. [_First2, _Last2) return _STD lexicographical_compare(_First1, _Last1, _First2, _Last2, less<>()); } @@ -4572,59 +4625,47 @@ _NODISCARD bool lexicographical_compare( // FUNCTION TEMPLATE find template -bool _Within_limits(const _Ty& _Val, true_type, true_type, _Any_tag) { // signed _Elem, signed _Ty +_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, true_type, _Any_tag) { // signed _Elem, signed _Ty return SCHAR_MIN <= _Val && _Val <= SCHAR_MAX; } template -bool _Within_limits(const _Ty& _Val, true_type, false_type, true_type) { +_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, false_type, true_type) { // signed _Elem, unsigned _Ty, -1 == static_cast<_Ty>(-1) return _Val <= SCHAR_MAX || static_cast<_Ty>(SCHAR_MIN) <= _Val; } template -bool _Within_limits(const _Ty& _Val, true_type, false_type, false_type) { +_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, false_type, false_type) { // signed _Elem, unsigned _Ty, -1 != static_cast<_Ty>(-1) return _Val <= SCHAR_MAX; } template -bool _Within_limits(const _Ty& _Val, false_type, true_type, _Any_tag) { +_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, false_type, true_type, _Any_tag) { // unsigned _Elem, signed _Ty return 0 <= _Val && _Val <= UCHAR_MAX; } template -bool _Within_limits(const _Ty& _Val, false_type, false_type, _Any_tag) { +_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, false_type, false_type, _Any_tag) { // unsigned _Elem, unsigned _Ty return _Val <= UCHAR_MAX; } template -bool _Within_limits(_InIt, const _Ty& _Val) { // check whether _Val is within the limits of _Elem +_NODISCARD constexpr bool _Within_limits(_InIt, const _Ty& _Val) { // check whether _Val is within the limits of _Elem using _Elem = remove_pointer_t<_InIt>; return _Within_limits(_Val, is_signed<_Elem>{}, is_signed<_Ty>{}, bool_constant<-1 == static_cast<_Ty>(-1)>{}); } template -bool _Within_limits(_InIt, const bool&) { // bools are always within the limits of _Elem +_NODISCARD constexpr bool _Within_limits(_InIt, const bool&) { // bools are always within the limits of _Elem return true; } template -_InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, true_type) { - // find first byte matching integral _Val - if (!_Within_limits(_First, _Val)) { - return _Last; - } - - _First = - static_cast<_InIt>(_CSTD memchr(_First, static_cast(_Val), static_cast(_Last - _First))); - return _First ? _First : _Last; -} - -template -_InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, false_type) { +_NODISCARD constexpr _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, false_type) { // find first matching _Val for (; _First != _Last; ++_First) { if (*_First == _Val) { @@ -4636,7 +4677,24 @@ _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, false_t } template -_InIt _Find_unchecked(const _InIt _First, const _InIt _Last, const _Ty& _Val) { +_NODISCARD _CONSTEXPR20_ICE _InIt _Find_unchecked1(_InIt _First, const _InIt _Last, const _Ty& _Val, true_type) { + // find first byte matching integral _Val + if (!_Within_limits(_First, _Val)) { + return _Last; + } + +#ifdef __cpp_lib_is_constant_evaluated + if (_STD is_constant_evaluated()) { + return _Find_unchecked1(_First, _Last, _Val, false_type{}); + } +#endif // __cpp_lib_is_constant_evaluated + _First = + static_cast<_InIt>(_CSTD memchr(_First, static_cast(_Val), static_cast(_Last - _First))); + return _First ? _First : _Last; +} + +template +_NODISCARD _CONSTEXPR20_ICE _InIt _Find_unchecked(const _InIt _First, const _InIt _Last, const _Ty& _Val) { // find first matching _Val; choose optimization // activate optimization for pointers to (const) bytes and integral values using _Memchr_opt = bool_constant< @@ -4647,7 +4705,7 @@ _InIt _Find_unchecked(const _InIt _First, const _InIt _Last, const _Ty& _Val) { } template -_NODISCARD _InIt find(_InIt _First, const _InIt _Last, const _Ty& _Val) { // find first matching _Val +_NODISCARD _CONSTEXPR20_ICE _InIt find(_InIt _First, const _InIt _Last, const _Ty& _Val) { // find first matching _Val _Adl_verify_range(_First, _Last); _Seek_wrapped(_First, _Find_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Val)); return _First; @@ -4660,7 +4718,7 @@ _NODISCARD _FwdIt find(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, const _ // FUNCTION TEMPLATE count template -_NODISCARD _Iter_diff_t<_InIt> count(const _InIt _First, const _InIt _Last, const _Ty& _Val) { +_NODISCARD _CONSTEXPR20 _Iter_diff_t<_InIt> count(const _InIt _First, const _InIt _Last, const _Ty& _Val) { // count elements that match _Val _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -4684,7 +4742,7 @@ _NODISCARD _Iter_diff_t<_FwdIt> count( // FUNCTION TEMPLATE is_permutation template -_NODISCARD _InIt _Find_pr(_InIt _First, const _InIt _Last, const _Ty& _Val, _Pr _Pred) { +_NODISCARD constexpr _InIt _Find_pr(_InIt _First, const _InIt _Last, const _Ty& _Val, _Pr _Pred) { for (; _First != _Last; ++_First) { if (_Pred(*_First, _Val)) { break; @@ -4695,7 +4753,7 @@ _NODISCARD _InIt _Find_pr(_InIt _First, const _InIt _Last, const _Ty& _Val, _Pr } template -_NODISCARD _Iter_diff_t<_InIt> _Count_pr(_InIt _First, const _InIt _Last, const _Ty& _Val, _Pr _Pred) { +_NODISCARD constexpr _Iter_diff_t<_InIt> _Count_pr(_InIt _First, const _InIt _Last, const _Ty& _Val, _Pr _Pred) { _Iter_diff_t<_InIt> _Count = 0; for (; _First != _Last; ++_First) { @@ -4728,7 +4786,7 @@ void _Trim_matching_suffixes( #endif // !_HAS_IF_CONSTEXPR template -_NODISCARD bool _Check_match_counts( +_NODISCARD _CONSTEXPR20 bool _Check_match_counts( const _FwdIt1 _First1, _FwdIt1 _Last1, const _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, _Last2), after matching prefix removal _STL_INTERNAL_CHECK(!_Pred(*_First1, *_First2)); @@ -4764,7 +4822,7 @@ _NODISCARD bool _Check_match_counts( } template -_NODISCARD bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred for (; _First1 != _Last1; ++_First1, (void) ++_First2) { // trim matching prefix if (!_Pred(*_First1, *_First2)) { @@ -4781,7 +4839,7 @@ _NODISCARD bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdI } template -_NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred _Adl_verify_range(_First1, _Last1); const auto _UFirst1 = _Get_unwrapped(_First1); @@ -4792,14 +4850,15 @@ _NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template , int> = 0> -_NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _RightTy (&_First2)[_RightSize], _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool is_permutation( + _FwdIt1 _First1, _FwdIt1 _Last1, _RightTy (&_First2)[_RightSize], _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred return _STD is_permutation(_First1, _Last1, _Array_iterator<_RightTy, _RightSize>(_First2), _Pass_fn(_Pred)); } #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { +_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { // test if [_First1, _Last1) == permuted [_First2, ...) return _STD is_permutation(_First1, _Last1, _First2, equal_to<>()); } @@ -4807,14 +4866,14 @@ bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template -_NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _RightTy (&_First2)[_RightSize]) { +_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _RightTy (&_First2)[_RightSize]) { // test if [_First1, _Last1) == permuted [_First2, ...) return _STD is_permutation(_First1, _Last1, _First2, equal_to<>()); } #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS template -bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, +_CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, forward_iterator_tag, forward_iterator_tag) { // test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred, arbitrary iterators for (;;) { // trim matching prefix @@ -4855,7 +4914,7 @@ bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, } template -bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, +_CONSTEXPR20 bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, random_access_iterator_tag, random_access_iterator_tag) { // test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred, random-access iterators if (_Last1 - _First1 != _Last2 - _First2) { @@ -4873,7 +4932,8 @@ bool _Is_permutation_unchecked(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, } template -_NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 bool is_permutation( + _FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -4882,7 +4942,7 @@ _NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, } template -_NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { +_NODISCARD _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { // test if [_First1, _Last1) == permuted [_First2, _Last2) return _STD is_permutation(_First1, _Last1, _First2, _Last2, equal_to<>()); } @@ -4890,7 +4950,7 @@ _NODISCARD bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, // FUNCTION TEMPLATE reverse #if _HAS_IF_CONSTEXPR template -void reverse(const _BidIt _First, const _BidIt _Last) { // reverse elements in [_First, _Last) +_CONSTEXPR20_ICE void reverse(const _BidIt _First, const _BidIt _Last) { // reverse elements in [_First, _Last) _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); auto _ULast = _Get_unwrapped(_Last); @@ -4898,21 +4958,45 @@ void reverse(const _BidIt _First, const _BidIt _Last) { // reverse elements in [ using _Elem = remove_pointer_t; constexpr bool _Allow_vectorization = conjunction_v, _Is_trivially_swappable<_Elem>, negation>>; + if constexpr (_Allow_vectorization && sizeof(_Elem) == 1) { - __std_reverse_trivially_swappable_1(_UFirst, _ULast); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + __std_reverse_trivially_swappable_1(_UFirst, _ULast); + return; + } } else if constexpr (_Allow_vectorization && sizeof(_Elem) == 2) { - __std_reverse_trivially_swappable_2(_UFirst, _ULast); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + __std_reverse_trivially_swappable_2(_UFirst, _ULast); + return; + } } else if constexpr (_Allow_vectorization && sizeof(_Elem) == 4) { - __std_reverse_trivially_swappable_4(_UFirst, _ULast); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + __std_reverse_trivially_swappable_4(_UFirst, _ULast); + return; + } } else if constexpr (_Allow_vectorization && sizeof(_Elem) == 8) { - __std_reverse_trivially_swappable_8(_UFirst, _ULast); - } else -#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) - { - for (; _UFirst != _ULast && _UFirst != --_ULast; ++_UFirst) { - _STD iter_swap(_UFirst, _ULast); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + __std_reverse_trivially_swappable_8(_UFirst, _ULast); + return; } } +#endif // (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) + + for (; _UFirst != _ULast && _UFirst != --_ULast; ++_UFirst) { + _STD iter_swap(_UFirst, _ULast); + } } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template @@ -4986,7 +5070,7 @@ void reverse(_ExPo&&, _BidIt _First, _BidIt _Last) noexcept /* terminates */ { // FUNCTION TEMPLATE rotate template -pair<_BidIt, _BidIt> _Reverse_until_sentinel_unchecked(_BidIt _First, _BidIt _Sentinel, _BidIt _Last) { +constexpr pair<_BidIt, _BidIt> _Reverse_until_sentinel_unchecked(_BidIt _First, _BidIt _Sentinel, _BidIt _Last) { // reverse until either _First or _Last hits _Sentinel while (_First != _Sentinel && _Last != _Sentinel) { _STD iter_swap(_First, --_Last); @@ -4998,7 +5082,7 @@ pair<_BidIt, _BidIt> _Reverse_until_sentinel_unchecked(_BidIt _First, _BidIt _Se #if _HAS_IF_CONSTEXPR template -_FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { +_CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { // exchange the ranges [_First, _Mid) and [_Mid, _Last) // that is, rotates [_First, _Last) left by distance(_First, _Mid) positions // returns the iterator pointing at *_First's new home @@ -5130,7 +5214,7 @@ _FwdIt rotate(_ExPo&&, _FwdIt _First, _FwdIt _Mid, _FwdIt _Last) noexcept /* ter // FUNCTION TEMPLATE find_if template -_NODISCARD _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) { // find first satisfying _Pred +_NODISCARD _CONSTEXPR20 _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) { // find first satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); @@ -5146,7 +5230,7 @@ _NODISCARD _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) { // find f // FUNCTION TEMPLATE lower_bound template -_NODISCARD _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { +_NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // find first element not before _Val, using _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -5167,6 +5251,12 @@ _NODISCARD _FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val return _First; } +template +_NODISCARD _CONSTEXPR20 _FwdIt lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { + // find first element not before _Val, using operator< + return _STD lower_bound(_First, _Last, _Val, less<>()); +} + // CLASS TEMPLATE _Rng_from_urng template class _Rng_from_urng { // wrap a URNG as an RNG diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 4ba1f6639b1..06594e2bf82 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -128,6 +128,7 @@ // _HAS_CXX20 directly controls: // P0020R6 atomic, atomic, atomic // P0122R7 +// P0202R3 constexpr For And exchange() // P0318R1 unwrap_reference, unwrap_ref_decay // P0325R4 to_array() // P0356R5 bind_front() @@ -155,6 +156,7 @@ // P0769R2 shift_left(), shift_right() // P0811R3 midpoint(), lerp() // (partially implemented, lerp() not yet constexpr) +// P0879R0 constexpr For Swapping Functions // P0887R1 type_identity // P0896R4 Ranges // (partially implemented) @@ -1025,7 +1027,8 @@ #define __cpp_lib_unwrap_ref 201811L #ifdef __cpp_lib_is_constant_evaluated -#define __cpp_lib_constexpr_numeric 201911L +#define __cpp_lib_constexpr_algorithms 201806L +#define __cpp_lib_constexpr_numeric 201911L #endif // __cpp_lib_is_constant_evaluated #endif // _HAS_CXX20 diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index f50071d081e..5bf70d448c2 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -40,6 +40,24 @@ utilities\template.bitset\bitset.cons\string_ctor.pass.cpp # This test has undefined behavior under N4842 [basic.start.term]/6 thread\futures\futures.task\futures.task.members\dtor.pass.cpp +# libcxx is incorrect on what the type passed to allocator construct should be +# See https://reviews.llvm.org/D61364 +containers\associative\map\map.modifiers\insert_and_emplace_allocator_requirements.pass.cpp +containers\associative\set\insert_and_emplace_allocator_requirements.pass.cpp +containers\unord\unord.map\unord.map.modifiers\insert_and_emplace_allocator_requirements.pass.cpp +containers\unord\unord.set\insert_and_emplace_allocator_requirements.pass.cpp + +# libcxx incorrectly assumes moved-from non-POCMA containers are empty +# See https://reviews.llvm.org/D61366 +containers\associative\map\map.cons\move_assign.pass.cpp +containers\associative\multimap\multimap.cons\move_assign.pass.cpp +containers\associative\multiset\multiset.cons\move_assign.pass.cpp +containers\associative\set\set.cons\move_assign.pass.cpp + +# libcxx incorrectly thinks subspan can produce a span of dynamic extent +# See https://reviews.llvm.org/D73138 +containers\views\span.sub\subspan.pass.cpp + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" @@ -196,85 +214,6 @@ utilities\tuple\tuple.tuple\tuple.apply\apply_large_arity.pass.cpp # C++20 P0019R8 "atomic_ref" language.support\support.limits\support.limits.general\atomic.version.pass.cpp -# C++20 P0202R3 "constexpr For And exchange()" -algorithms\alg.modifying.operations\alg.copy\copy_backward.pass.cpp -algorithms\alg.modifying.operations\alg.copy\copy_if.pass.cpp -algorithms\alg.modifying.operations\alg.copy\copy_n.pass.cpp -algorithms\alg.modifying.operations\alg.copy\copy.pass.cpp -algorithms\alg.modifying.operations\alg.fill\fill_n.pass.cpp -algorithms\alg.modifying.operations\alg.fill\fill.pass.cpp -algorithms\alg.modifying.operations\alg.generate\generate_n.pass.cpp -algorithms\alg.modifying.operations\alg.generate\generate.pass.cpp -algorithms\alg.modifying.operations\alg.partitions\is_partitioned.pass.cpp -algorithms\alg.modifying.operations\alg.partitions\partition_copy.pass.cpp -algorithms\alg.modifying.operations\alg.partitions\partition_point.pass.cpp -algorithms\alg.modifying.operations\alg.remove\remove_copy_if.pass.cpp -algorithms\alg.modifying.operations\alg.remove\remove_copy.pass.cpp -algorithms\alg.modifying.operations\alg.remove\remove_if.pass.cpp -algorithms\alg.modifying.operations\alg.remove\remove.pass.cpp -algorithms\alg.modifying.operations\alg.replace\replace_copy_if.pass.cpp -algorithms\alg.modifying.operations\alg.replace\replace_copy.pass.cpp -algorithms\alg.modifying.operations\alg.replace\replace_if.pass.cpp -algorithms\alg.modifying.operations\alg.replace\replace.pass.cpp -algorithms\alg.modifying.operations\alg.reverse\reverse_copy.pass.cpp -algorithms\alg.modifying.operations\alg.transform\binary_transform.pass.cpp -algorithms\alg.modifying.operations\alg.transform\unary_transform.pass.cpp -algorithms\alg.modifying.operations\alg.unique\unique_copy_pred.pass.cpp -algorithms\alg.modifying.operations\alg.unique\unique_copy.pass.cpp -algorithms\alg.modifying.operations\alg.unique\unique_pred.pass.cpp -algorithms\alg.modifying.operations\alg.unique\unique.pass.cpp -algorithms\alg.nonmodifying\alg.adjacent.find\adjacent_find_pred.pass.cpp -algorithms\alg.nonmodifying\alg.adjacent.find\adjacent_find.pass.cpp -algorithms\alg.nonmodifying\alg.all_of\all_of.pass.cpp -algorithms\alg.nonmodifying\alg.any_of\any_of.pass.cpp -algorithms\alg.nonmodifying\alg.count\count_if.pass.cpp -algorithms\alg.nonmodifying\alg.count\count.pass.cpp -algorithms\alg.nonmodifying\alg.equal\equal_pred.pass.cpp -algorithms\alg.nonmodifying\alg.equal\equal.pass.cpp -algorithms\alg.nonmodifying\alg.find.end\find_end_pred.pass.cpp -algorithms\alg.nonmodifying\alg.find.end\find_end.pass.cpp -algorithms\alg.nonmodifying\alg.find.first.of\find_first_of_pred.pass.cpp -algorithms\alg.nonmodifying\alg.find.first.of\find_first_of.pass.cpp -algorithms\alg.nonmodifying\alg.find\find_if_not.pass.cpp -algorithms\alg.nonmodifying\alg.find\find_if.pass.cpp -algorithms\alg.nonmodifying\alg.find\find.pass.cpp -algorithms\alg.nonmodifying\alg.foreach\for_each_n.pass.cpp -algorithms\alg.nonmodifying\alg.foreach\test.pass.cpp -algorithms\alg.nonmodifying\alg.is_permutation\is_permutation_pred.pass.cpp -algorithms\alg.nonmodifying\alg.is_permutation\is_permutation.pass.cpp -algorithms\alg.nonmodifying\alg.none_of\none_of.pass.cpp -algorithms\alg.nonmodifying\alg.search\search_n_pred.pass.cpp -algorithms\alg.nonmodifying\alg.search\search_n.pass.cpp -algorithms\alg.nonmodifying\alg.search\search_pred.pass.cpp -algorithms\alg.nonmodifying\alg.search\search.pass.cpp -algorithms\alg.nonmodifying\mismatch\mismatch_pred.pass.cpp -algorithms\alg.nonmodifying\mismatch\mismatch.pass.cpp -algorithms\alg.sorting\alg.binary.search\binary.search\binary_search_comp.pass.cpp -algorithms\alg.sorting\alg.binary.search\binary.search\binary_search.pass.cpp -algorithms\alg.sorting\alg.binary.search\equal.range\equal_range_comp.pass.cpp -algorithms\alg.sorting\alg.binary.search\equal.range\equal_range.pass.cpp -algorithms\alg.sorting\alg.binary.search\lower.bound\lower_bound_comp.pass.cpp -algorithms\alg.sorting\alg.binary.search\lower.bound\lower_bound.pass.cpp -algorithms\alg.sorting\alg.binary.search\upper.bound\upper_bound_comp.pass.cpp -algorithms\alg.sorting\alg.binary.search\upper.bound\upper_bound.pass.cpp -algorithms\alg.sorting\alg.heap.operations\is.heap\is_heap_comp.pass.cpp -algorithms\alg.sorting\alg.heap.operations\is.heap\is_heap_until_comp.pass.cpp -algorithms\alg.sorting\alg.heap.operations\is.heap\is_heap_until.pass.cpp -algorithms\alg.sorting\alg.heap.operations\is.heap\is_heap.pass.cpp -algorithms\alg.sorting\alg.lex.comparison\lexicographical_compare_comp.pass.cpp -algorithms\alg.sorting\alg.lex.comparison\lexicographical_compare.pass.cpp -algorithms\alg.sorting\alg.set.operations\includes\includes_comp.pass.cpp -algorithms\alg.sorting\alg.set.operations\includes\includes.pass.cpp -algorithms\alg.sorting\alg.set.operations\set.intersection\set_intersection_comp.pass.cpp -algorithms\alg.sorting\alg.set.operations\set.intersection\set_intersection.pass.cpp -algorithms\alg.sorting\alg.sort\is.sorted\is_sorted_comp.pass.cpp -algorithms\alg.sorting\alg.sort\is.sorted\is_sorted_until_comp.pass.cpp -algorithms\alg.sorting\alg.sort\is.sorted\is_sorted_until.pass.cpp -algorithms\alg.sorting\alg.sort\is.sorted\is_sorted.pass.cpp -containers\views\span.sub\first.pass.cpp -containers\views\span.sub\last.pass.cpp -containers\views\span.sub\subspan.pass.cpp -utilities\utility\exchange\exchange.pass.cpp # C++20 P0355R7 " Calendars And Time Zones" utilities\time\days.pass.cpp @@ -512,13 +451,6 @@ language.support\support.limits\support.limits.general\compare.version.pass.cpp language.support\support.limits\support.limits.general\numeric.version.pass.cpp numerics\c.math\c.math.lerp\c.math.lerp.pass.cpp -# C++20 P0879R0 "constexpr For Swapping Functions" -algorithms\alg.modifying.operations\alg.swap\iter_swap.pass.cpp -algorithms\alg.modifying.operations\alg.swap\swap_ranges.pass.cpp -language.support\support.limits\support.limits.general\algorithm.version.pass.cpp -utilities\utility\utility.swap\swap.pass.cpp -utilities\utility\utility.swap\swap_array.pass.cpp - # C++20 P0896R4 "" language.support\support.limits\support.limits.general\algorithm.version.pass.cpp language.support\support.limits\support.limits.general\functional.version.pass.cpp @@ -1030,17 +962,5 @@ containers\unord\unord.multimap\unord.multimap.cnstr\deduct.pass.cpp containers\unord\unord.multimap\unord.multimap.cnstr\deduct_const.pass.cpp utilities\tuple\tuple.tuple\tuple.cnstr\deduct.pass.cpp -# Not yet analyzed. Assertion failed: m1.empty() -containers\associative\map\map.cons\move_assign.pass.cpp -containers\associative\multimap\multimap.cons\move_assign.pass.cpp -containers\associative\multiset\multiset.cons\move_assign.pass.cpp -containers\associative\set\set.cons\move_assign.pass.cpp - -# Not yet analyzed. Assertion failed: controller->check() -containers\associative\map\map.modifiers\insert_and_emplace_allocator_requirements.pass.cpp -containers\associative\set\insert_and_emplace_allocator_requirements.pass.cpp -containers\unord\unord.map\unord.map.modifiers\insert_and_emplace_allocator_requirements.pass.cpp -containers\unord\unord.set\insert_and_emplace_allocator_requirements.pass.cpp - # Not yet analyzed. Assertion failed: f16_8.out(mbs, c16, c_c16p, c_c16p, c8, c8+4, c8p) == F32_8::ok localization\locale.categories\category.ctype\locale.codecvt\locale.codecvt.members\utf_sanity_check.pass.cpp