diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 2a8c5f93678..41e5d8acfdd 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -135,7 +135,6 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/unordered_map ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/unordered_set ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/vector - ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/xutility ${CMAKE_CURRENT_LIST_DIR}/inc/filesystem ${CMAKE_CURRENT_LIST_DIR}/inc/forward_list ${CMAKE_CURRENT_LIST_DIR}/inc/fstream diff --git a/stl/inc/algorithm b/stl/inc/algorithm index ad55394139c..716eca572be 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1733,54 +1733,12 @@ _DestTy* remove_copy_if( #endif // _ITERATOR_DEBUG_ARRAY_OVERLOADS #endif // _HAS_CXX17 -// FUNCTION TEMPLATE remove -template -_NODISCARD _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); - _UFirst = _Find_unchecked(_UFirst, _ULast, _Val); - auto _UNext = _UFirst; - if (_UFirst != _ULast) { - while (++_UFirst != _ULast) { - if (!(*_UFirst == _Val)) { - *_UNext = _STD move(*_UFirst); - ++_UNext; - } - } - } - - _Seek_wrapped(_First, _UNext); - return _First; -} - #if _HAS_CXX17 template = 0> _NODISCARD _FwdIt remove( _ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) noexcept; // terminates #endif // _HAS_CXX17 -// FUNCTION TEMPLATE remove_if -template -_NODISCARD _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); - _UFirst = _STD find_if(_UFirst, _ULast, _Pass_fn(_Pred)); - auto _UNext = _UFirst; - if (_UFirst != _ULast) { - while (++_UFirst != _ULast) { - if (!_Pred(*_UFirst)) { - *_UNext = _STD move(*_UFirst); - ++_UNext; - } - } - } - - _Seek_wrapped(_First, _UNext); - return _First; -} - #if _HAS_CXX17 template = 0> _NODISCARD _FwdIt remove_if(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept; // terminates diff --git a/stl/inc/deque b/stl/inc/deque index e3729e32e25..2d5a6b949bf 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1608,6 +1608,18 @@ _NODISCARD bool operator>=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Al return !(_Left < _Right); } +#if _HAS_CXX20 +template +void erase(deque<_Ty, _Alloc>& _Cont, const _Uty& _Val) { + _Erase_remove(_Cont, _Val); +} + +template +void erase_if(deque<_Ty, _Alloc>& _Cont, _Pr _Pred) { + _Erase_remove_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template diff --git a/stl/inc/experimental/deque b/stl/inc/experimental/deque index cf11ee76774..3b0bf2eb361 100644 --- a/stl/inc/experimental/deque +++ b/stl/inc/experimental/deque @@ -10,7 +10,6 @@ #if _STL_COMPILER_PREPROCESSOR #include -#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -25,13 +24,13 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(deque<_Ty, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(deque<_Ty, _Alloc>& _Cont, _Pr _Pred) { _Erase_remove_if(_Cont, _Pass_fn(_Pred)); } // FUNCTION TEMPLATE erase template - void erase(deque<_Ty, _Alloc>& _Cont, const _Uty& _Val) { // erase each element matching _Val + _DEPRECATE_EXPERIMENTAL_ERASE void erase(deque<_Ty, _Alloc>& _Cont, const _Uty& _Val) { _Erase_remove(_Cont, _Val); } diff --git a/stl/inc/experimental/forward_list b/stl/inc/experimental/forward_list index acdede41789..ec2323808a8 100644 --- a/stl/inc/experimental/forward_list +++ b/stl/inc/experimental/forward_list @@ -24,13 +24,13 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(forward_list<_Ty, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(forward_list<_Ty, _Alloc>& _Cont, _Pr _Pred) { _Cont.remove_if(_Pass_fn(_Pred)); } // FUNCTION TEMPLATE erase template - void erase(forward_list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { // erase each element matching _Val + _DEPRECATE_EXPERIMENTAL_ERASE void erase(forward_list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { _Cont.remove_if([&](_Ty& _Elem) { return _Elem == _Val; }); } diff --git a/stl/inc/experimental/list b/stl/inc/experimental/list index fa37101cf8e..d4d1314bcf8 100644 --- a/stl/inc/experimental/list +++ b/stl/inc/experimental/list @@ -24,13 +24,13 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(list<_Ty, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(list<_Ty, _Alloc>& _Cont, _Pr _Pred) { _Cont.remove_if(_Pass_fn(_Pred)); } // FUNCTION TEMPLATE erase template - void erase(list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { // erase each element matching _Val + _DEPRECATE_EXPERIMENTAL_ERASE void erase(list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { _Cont.remove_if([&](_Ty& _Elem) { return _Elem == _Val; }); } diff --git a/stl/inc/experimental/map b/stl/inc/experimental/map index 9a3f395b1f5..3c5bab0cd3c 100644 --- a/stl/inc/experimental/map +++ b/stl/inc/experimental/map @@ -9,7 +9,6 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #pragma pack(push, _CRT_PACKING) @@ -25,12 +24,12 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(map<_Kty, _Ty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(map<_Kty, _Ty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } template - void erase_if(multimap<_Kty, _Ty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(multimap<_Kty, _Ty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } diff --git a/stl/inc/experimental/set b/stl/inc/experimental/set index 7f22f95f635..9fc738f5d49 100644 --- a/stl/inc/experimental/set +++ b/stl/inc/experimental/set @@ -9,7 +9,6 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #pragma pack(push, _CRT_PACKING) @@ -25,12 +24,12 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(set<_Kty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(set<_Kty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } template - void erase_if(multiset<_Kty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(multiset<_Kty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } diff --git a/stl/inc/experimental/string b/stl/inc/experimental/string index 05ae08bbd44..a6bc3945435 100644 --- a/stl/inc/experimental/string +++ b/stl/inc/experimental/string @@ -9,7 +9,6 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #pragma pack(push, _CRT_PACKING) @@ -25,13 +24,13 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(basic_string<_Elem, _Traits, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(basic_string<_Elem, _Traits, _Alloc>& _Cont, _Pr _Pred) { _Erase_remove_if(_Cont, _Pass_fn(_Pred)); } // FUNCTION TEMPLATE erase template - void erase(basic_string<_Elem, _Traits, _Alloc>& _Cont, const _Uty& _Val) { // erase each element matching _Val + _DEPRECATE_EXPERIMENTAL_ERASE void erase(basic_string<_Elem, _Traits, _Alloc>& _Cont, const _Uty& _Val) { _Erase_remove(_Cont, _Val); } diff --git a/stl/inc/experimental/unordered_map b/stl/inc/experimental/unordered_map index 2fe046632f9..106746b0e57 100644 --- a/stl/inc/experimental/unordered_map +++ b/stl/inc/experimental/unordered_map @@ -9,7 +9,6 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #pragma pack(push, _CRT_PACKING) @@ -25,14 +24,14 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, - _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if( + unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } template - void erase_if(unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, - _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if( + unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } diff --git a/stl/inc/experimental/unordered_set b/stl/inc/experimental/unordered_set index d6f85d28880..44f4e6c4db5 100644 --- a/stl/inc/experimental/unordered_set +++ b/stl/inc/experimental/unordered_set @@ -9,7 +9,6 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #pragma pack(push, _CRT_PACKING) @@ -25,14 +24,13 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, - _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } template - void erase_if(unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, - _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if( + unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); } diff --git a/stl/inc/experimental/vector b/stl/inc/experimental/vector index 77dd04cab70..e4422ebabd2 100644 --- a/stl/inc/experimental/vector +++ b/stl/inc/experimental/vector @@ -9,7 +9,6 @@ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #pragma pack(push, _CRT_PACKING) @@ -25,13 +24,13 @@ namespace experimental { // FUNCTION TEMPLATE erase_if template - void erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + _DEPRECATE_EXPERIMENTAL_ERASE void erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { _Erase_remove_if(_Cont, _Pass_fn(_Pred)); } // FUNCTION TEMPLATE erase template - void erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { // erase each element matching _Val + _DEPRECATE_EXPERIMENTAL_ERASE void erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { _Erase_remove(_Cont, _Val); } diff --git a/stl/inc/experimental/xutility b/stl/inc/experimental/xutility deleted file mode 100644 index 83ee7564446..00000000000 --- a/stl/inc/experimental/xutility +++ /dev/null @@ -1,69 +0,0 @@ -// xutility experimental header - -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#pragma once -#ifndef _EXPERIMENTAL_XUTILITY_ -#define _EXPERIMENTAL_XUTILITY_ -#include -#if _STL_COMPILER_PREPROCESSOR - -#include -#include - -#pragma pack(push, _CRT_PACKING) -#pragma warning(push, _STL_WARNING_LEVEL) -#pragma warning(disable : _STL_DISABLED_WARNINGS) -_STL_DISABLE_CLANG_WARNINGS -#pragma push_macro("new") -#undef new - -_STD_BEGIN -namespace experimental { - inline namespace fundamentals_v2 { - - // FUNCTION TEMPLATE _Erase_nodes_if - template - void _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred - auto _First = _Cont.begin(); - const auto _Last = _Cont.end(); - while (_First != _Last) { - if (_Pred(*_First)) { - _First = _Cont.erase(_First); - } else { - ++_First; - } - } - } - - - // FUNCTION TEMPLATE _Erase_remove_if - template - void _Erase_remove_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred - auto _First = _Cont.begin(); - const auto _Last = _Cont.end(); - _Seek_wrapped(_First, _STD remove_if(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Pred)); - _Cont.erase(_First, _Last); - } - - // FUNCTION TEMPLATE _Erase_remove - template - void _Erase_remove(_Container& _Cont, const _Uty& _Val) { // erase each element matching _Val - auto _First = _Cont.begin(); - const auto _Last = _Cont.end(); - _Seek_wrapped(_First, _STD remove(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Val)); - _Cont.erase(_First, _Last); - } - - } // namespace fundamentals_v2 -} // namespace experimental -_STD_END - -#pragma pop_macro("new") -_STL_RESTORE_CLANG_WARNINGS -#pragma warning(pop) -#pragma pack(pop) - -#endif // _STL_COMPILER_PREPROCESSOR -#endif // _EXPERIMENTAL_XUTILITY_ diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 34944e4ca0d..b1a6497e2b1 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -1526,6 +1526,18 @@ _NODISCARD bool operator>=(const forward_list<_Ty, _Alloc>& _Left, const forward return !(_Left < _Right); } +#if _HAS_CXX20 +template +void erase(forward_list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { + _Cont.remove_if([&](_Ty& _Elem) { return _Elem == _Val; }); +} + +template +void erase_if(forward_list<_Ty, _Alloc>& _Cont, _Pr _Pred) { + _Cont.remove_if(_Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template diff --git a/stl/inc/list b/stl/inc/list index 208c0ea7a8f..b49799830d8 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1816,6 +1816,18 @@ _NODISCARD bool operator>=(const list<_Ty, _Alloc>& _Left, const list<_Ty, _Allo return !(_Left < _Right); } +#if _HAS_CXX20 +template +void erase(list<_Ty, _Alloc>& _Cont, const _Uty& _Val) { + _Cont.remove_if([&](_Ty& _Elem) { return _Elem == _Val; }); +} + +template +void erase_if(list<_Ty, _Alloc>& _Cont, _Pr _Pred) { + _Cont.remove_if(_Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template diff --git a/stl/inc/map b/stl/inc/map index 477df64c8d1..2d93d3815c4 100644 --- a/stl/inc/map +++ b/stl/inc/map @@ -369,6 +369,13 @@ void swap(map<_Kty, _Ty, _Pr, _Alloc>& _Left, map<_Kty, _Ty, _Pr, _Alloc>& _Righ _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(map<_Kty, _Ty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + // CLASS TEMPLATE multimap template , class _Alloc = allocator>> class multimap : public _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, true>> { @@ -516,6 +523,13 @@ void swap(multimap<_Kty, _Ty, _Pr, _Alloc>& _Left, multimap<_Kty, _Ty, _Pr, _All _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(multimap<_Kty, _Ty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template > diff --git a/stl/inc/set b/stl/inc/set index 9031bb02c85..47ec4bd0c50 100644 --- a/stl/inc/set +++ b/stl/inc/set @@ -179,6 +179,13 @@ void swap(set<_Kty, _Pr, _Alloc>& _Left, set<_Kty, _Pr, _Alloc>& _Right) noexcep _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(set<_Kty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + // CLASS TEMPLATE multiset template , class _Alloc = allocator<_Kty>> class multiset : public _Tree<_Tset_traits<_Kty, _Pr, _Alloc, true>> { @@ -313,6 +320,13 @@ void swap(multiset<_Kty, _Pr, _Alloc>& _Left, multiset<_Kty, _Pr, _Alloc>& _Righ _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(multiset<_Kty, _Keylt, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template > diff --git a/stl/inc/unordered_map b/stl/inc/unordered_map index 605433b4299..e8b647aa1aa 100644 --- a/stl/inc/unordered_map +++ b/stl/inc/unordered_map @@ -473,6 +473,13 @@ void swap(unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left, _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + template _NODISCARD bool operator==(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) { @@ -761,6 +768,13 @@ void swap(unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left, _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + template _NODISCARD bool operator==(const unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) { diff --git a/stl/inc/unordered_set b/stl/inc/unordered_set index 27b05834708..d2bc48453b0 100644 --- a/stl/inc/unordered_set +++ b/stl/inc/unordered_set @@ -309,6 +309,13 @@ void swap(unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left, _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + template _NODISCARD bool operator==(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) { @@ -565,6 +572,13 @@ void swap(unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Left, _Left.swap(_Right); } +#if _HAS_CXX20 +template +void erase_if(unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) { + _Erase_nodes_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + template _NODISCARD bool operator==(const unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) { diff --git a/stl/inc/vector b/stl/inc/vector index cce19334bc7..15e292759d2 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -2863,6 +2863,18 @@ struct hash> { } }; +#if _HAS_CXX20 +template +void erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { + _Erase_remove(_Cont, _Val); +} + +template +void erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { + _Erase_remove_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 8705f7da73e..4edf5e33d06 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1994,6 +1994,80 @@ struct _Alloc_temporary { _Traits::destroy(_Al, _STD addressof(_Storage._Value)); } }; + +// FUNCTION TEMPLATE remove +template +_NODISCARD _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); + _UFirst = _Find_unchecked(_UFirst, _ULast, _Val); + auto _UNext = _UFirst; + if (_UFirst != _ULast) { + while (++_UFirst != _ULast) { + if (!(*_UFirst == _Val)) { + *_UNext = _STD move(*_UFirst); + ++_UNext; + } + } + } + + _Seek_wrapped(_First, _UNext); + return _First; +} + +// FUNCTION TEMPLATE remove_if +template +_NODISCARD _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); + _UFirst = _STD find_if(_UFirst, _ULast, _Pass_fn(_Pred)); + auto _UNext = _UFirst; + if (_UFirst != _ULast) { + while (++_UFirst != _ULast) { + if (!_Pred(*_UFirst)) { + *_UNext = _STD move(*_UFirst); + ++_UNext; + } + } + } + + _Seek_wrapped(_First, _UNext); + return _First; +} + +// FUNCTION TEMPLATE _Erase_remove +template +void _Erase_remove(_Container& _Cont, const _Uty& _Val) { // erase each element matching _Val + auto _First = _Cont.begin(); + const auto _Last = _Cont.end(); + _Seek_wrapped(_First, _STD remove(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Val)); + _Cont.erase(_First, _Last); +} + +// FUNCTION TEMPLATE _Erase_remove_if +template +void _Erase_remove_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + auto _First = _Cont.begin(); + const auto _Last = _Cont.end(); + _Seek_wrapped(_First, _STD remove_if(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Pred)); + _Cont.erase(_First, _Last); +} + +// FUNCTION TEMPLATE _Erase_nodes_if +template +void _Erase_nodes_if(_Container& _Cont, _Pr _Pred) { // erase each element satisfying _Pred + auto _First = _Cont.begin(); + const auto _Last = _Cont.end(); + while (_First != _Last) { + if (_Pred(*_First)) { + _First = _Cont.erase(_First); + } else { + ++_First; + } + } +} _STD_END #pragma pop_macro("new") diff --git a/stl/inc/xstring b/stl/inc/xstring index 82d82d73acf..ef7d278c659 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4575,6 +4575,18 @@ inline namespace literals { } // namespace string_literals } // namespace literals +#if _HAS_CXX20 +template +void erase(basic_string<_Elem, _Traits, _Alloc>& _Cont, const _Uty& _Val) { + _Erase_remove(_Cont, _Val); +} + +template +void erase_if(basic_string<_Elem, _Traits, _Alloc>& _Cont, _Pr _Pred) { + _Erase_remove_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + #if _HAS_CXX17 namespace pmr { template > diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index f0f7c619058..9b84fcc4e1b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -47,6 +47,7 @@ // P0898R3 Standard Library Concepts // P0919R3 Heterogeneous Lookup For Unordered Containers // P0966R1 string::reserve() Should Not Shrink +// P1209R0 erase_if(), erase() // P1227R2 Signed std::ssize(), Unsigned span::size() // (partially implemented) // P1357R1 is_bounded_array, is_unbounded_array @@ -835,7 +836,18 @@ #define _CXX20_DEPRECATE_IS_POD #endif // ^^^ warning disabled ^^^ -// next warning number: STL4026 +#if _HAS_CXX20 && !defined(_SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING) +#define _DEPRECATE_EXPERIMENTAL_ERASE \ + [[deprecated("warning STL4026: " \ + "std::experimental::erase() and std::experimental::erase_if() are deprecated by Microsoft and will " \ + "be REMOVED. They are superseded by std::erase() and std::erase_if(). " \ + "You can define _SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING to acknowledge that you have " \ + "received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_EXPERIMENTAL_ERASE +#endif // ^^^ warning disabled ^^^ + +// next warning number: STL4027 // LIBRARY FEATURE-TEST MACROS @@ -953,6 +965,7 @@ #endif // _HAS_STD_BOOLEAN #endif // defined(__cpp_concepts) && __cpp_concepts > 201507L +#define __cpp_lib_erase_if 201811L #define __cpp_lib_generic_unordered_lookup 201811L #define __cpp_lib_list_remove_return_type 201806L #define __cpp_lib_to_array 201907L