diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -186,7 +186,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_endian`` ``201907L`` ------------------------------------------------- ----------------- - ``__cpp_lib_erase_if`` ``201811L`` + ``__cpp_lib_erase_if`` ``202002L`` ------------------------------------------------- ----------------- ``__cpp_lib_generic_unordered_lookup`` *unimplemented* ------------------------------------------------- ----------------- diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -150,9 +150,11 @@ noexcept(noexcept(x.swap(y))); template - void erase(deque& c, const U& value); // C++20 + typename deque::size_type + erase(deque& c, const U& value); // C++20 template - void erase_if(deque& c, Predicate pred); // C++20 + typename deque::size_type + erase_if(deque& c, Predicate pred); // C++20 } // std @@ -3021,14 +3023,24 @@ #if _LIBCPP_STD_VER > 17 template -inline _LIBCPP_INLINE_VISIBILITY -void erase(deque<_Tp, _Allocator>& __c, const _Up& __v) -{ __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end()); } +inline _LIBCPP_INLINE_VISIBILITY typename deque<_Tp, _Allocator>::size_type +erase(deque<_Tp, _Allocator>& __c, const _Up& __v) { + auto __new_end = _VSTD::remove(__c.begin(), __c.end(), __v); + typename deque<_Tp, _Allocator>::size_type __erased_count = + std::distance(__new_end, __c.end()); + __c.erase(__new_end, __c.end()); + return __erased_count; +} template -inline _LIBCPP_INLINE_VISIBILITY -void erase_if(deque<_Tp, _Allocator>& __c, _Predicate __pred) -{ __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end()); } +inline _LIBCPP_INLINE_VISIBILITY typename deque<_Tp, _Allocator>::size_type +erase_if(deque<_Tp, _Allocator>& __c, _Predicate __pred) { + auto __new_end = _VSTD::remove_if(__c.begin(), __c.end(), __pred); + typename deque<_Tp, _Allocator>::size_type __erased_count = + std::distance(__new_end, __c.end()); + __c.erase(__new_end, __c.end()); + return __erased_count; +} #endif diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -169,9 +169,11 @@ noexcept(noexcept(x.swap(y))); template - void erase(forward_list& c, const U& value); // C++20 + typename forward_list::size_type + erase(forward_list& c, const U& value); // C++20 template - void erase_if(forward_list& c, Predicate pred); // C++20 + typename forward_list::size_type + erase_if(forward_list& c, Predicate pred); // C++20 } // std @@ -1765,13 +1767,17 @@ #if _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) -{ __c.remove_if(__pred); } + typename forward_list<_Tp, _Allocator>::size_type + erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) { + return __c.remove_if(__pred); +} template inline _LIBCPP_INLINE_VISIBILITY -void erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) -{ _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); } + typename forward_list<_Tp, _Allocator>::size_type + erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) { + return _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); +} #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/functional b/libcxx/include/functional --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -3080,15 +3080,19 @@ #endif // > C++17 template -inline void __libcpp_erase_if_container( _Container& __c, _Predicate __pred) -{ - for (typename _Container::iterator __iter = __c.begin(), __last = __c.end(); __iter != __last;) - { - if (__pred(*__iter)) - __iter = __c.erase(__iter); - else - ++__iter; - } +inline typename _Container::size_type +__libcpp_erase_if_container(_Container& __c, _Predicate __pred) { + typename _Container::size_type __old_size = __c.size(); + + for (typename _Container::iterator __iter = __c.begin(), __last = __c.end(); + __iter != __last;) { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } + + return __old_size - __c.size(); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/list b/libcxx/include/list --- a/libcxx/include/list +++ b/libcxx/include/list @@ -170,9 +170,11 @@ noexcept(noexcept(x.swap(y))); template - void erase(list& c, const U& value); // C++20 + typename list::size_type + erase(list& c, const U& value); // C++20 template - void erase_if(list& c, Predicate pred); // C++20 + typename list::size_type + erase_if(list& c, Predicate pred); // C++20 } // std @@ -2471,14 +2473,16 @@ #if _LIBCPP_STD_VER > 17 template -inline _LIBCPP_INLINE_VISIBILITY -void erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) -{ __c.remove_if(__pred); } +inline _LIBCPP_INLINE_VISIBILITY typename list<_Tp, _Allocator>::size_type +erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) { + return __c.remove_if(__pred); +} template -inline _LIBCPP_INLINE_VISIBILITY -void erase(list<_Tp, _Allocator>& __c, const _Up& __v) -{ _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); } +inline _LIBCPP_INLINE_VISIBILITY typename list<_Tp, _Allocator>::size_type +erase(list<_Tp, _Allocator>& __c, const _Up& __v) { + return _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); +} #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/map b/libcxx/include/map --- a/libcxx/include/map +++ b/libcxx/include/map @@ -254,7 +254,8 @@ noexcept(noexcept(x.swap(y))); template - void erase_if(map& c, Predicate pred); // C++20 +typename map::size_type +erase_if(map& c, Predicate pred); // C++20 template , @@ -469,7 +470,8 @@ noexcept(noexcept(x.swap(y))); template - void erase_if(multimap& c, Predicate pred); // C++20 +typename multimap::size_type +erase_if(multimap& c, Predicate pred); // C++20 } // std @@ -1653,10 +1655,13 @@ } #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename map<_Key, _Tp, _Compare, _Allocator>::size_type + erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif @@ -2235,10 +2240,14 @@ } #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename multimap<_Key, _Tp, _Compare, _Allocator>::size_type + erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, + _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/set b/libcxx/include/set --- a/libcxx/include/set +++ b/libcxx/include/set @@ -216,7 +216,8 @@ noexcept(noexcept(x.swap(y))); template - void erase_if(set& c, Predicate pred); // C++20 +typename set::size_type +erase_if(set& c, Predicate pred); // C++20 template , class Allocator = allocator> @@ -417,7 +418,8 @@ noexcept(noexcept(x.swap(y))); template - void erase_if(multiset& c, Predicate pred); // C++20 +typename multiset::size_type +erase_if(multiset& c, Predicate pred); // C++20 } // std @@ -960,8 +962,10 @@ #if _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename set<_Key, _Compare, _Allocator>::size_type + erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif template , @@ -1484,8 +1488,10 @@ #if _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename multiset<_Key, _Compare, _Allocator>::size_type + erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/string b/libcxx/include/string --- a/libcxx/include/string +++ b/libcxx/include/string @@ -437,9 +437,11 @@ getline(basic_istream& is, basic_string& str); template -void erase(basic_string& c, const U& value); // C++20 +typename basic_string::size_type +erase(basic_string& c, const U& value); // C++20 template -void erase_if(basic_string& c, Predicate pred); // C++20 +typename basic_string::size_type +erase_if(basic_string& c, Predicate pred); // C++20 typedef basic_string string; typedef basic_string wstring; @@ -4377,15 +4379,28 @@ #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) -{ __str.erase(_VSTD::remove(__str.begin(), __str.end(), __v), __str.end()); } + typename basic_string<_CharT, _Traits, _Allocator>::size_type + erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) { + auto __new_end = _VSTD::remove(__str.begin(), __str.end(), __v); + typename basic_string<_CharT, _Traits, _Allocator>::size_type __erased_count = + std::distance(__new_end, __c.end()); + __str.erase(__new_end, __str.end()); + return __erased_count; +} -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) -{ __str.erase(_VSTD::remove_if(__str.begin(), __str.end(), __pred), __str.end()); } + typename basic_string<_CharT, _Traits, _Allocator>::size_type + erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, + _Predicate __pred) { + auto __new_end = _VSTD::remove_if(__str.begin(), __str.end(), __pred); + typename basic_string<_CharT, _Traits, _Allocator>::size_type __erased_count = + std::distance(__new_end, __c.end()); + __str.erase(__new_end, __str.end()); + return __erased_count; +} #endif #if _LIBCPP_DEBUG_LEVEL >= 2 diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map --- a/libcxx/include/unordered_map +++ b/libcxx/include/unordered_map @@ -386,10 +386,12 @@ noexcept(noexcept(x.swap(y))); template - void erase_if(unordered_set& c, Predicate pred); // C++20 + typename unordered_map::size_type + erase_if(unordered_map& c, Predicate pred); // C++20 template - void erase_if(unordered_multiset& c, Predicate pred); // C++20 + typename unordered_multimap::size_type + erase_if(unordered_multimap& c, Predicate pred); // C++20 template bool @@ -1704,10 +1706,14 @@ } #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type + erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, + _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif template @@ -2402,10 +2408,14 @@ } #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type + erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, + _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif template diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set --- a/libcxx/include/unordered_set +++ b/libcxx/include/unordered_set @@ -341,10 +341,12 @@ noexcept(noexcept(x.swap(y))); template - void erase_if(unordered_set& c, Predicate pred); // C++20 + typename unordered_set::size_type + erase_if(unordered_set& c, Predicate pred); // C++20 template - void erase_if(unordered_multiset& c, Predicate pred); // C++20 + typename unordered_multiset::size_type + erase_if(unordered_multiset& c, Predicate pred); // C++20 template @@ -1006,10 +1008,14 @@ } #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type + erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, + _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif template @@ -1637,10 +1643,14 @@ } #if _LIBCPP_STD_VER > 17 -template +template inline _LIBCPP_INLINE_VISIBILITY -void erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) -{ __libcpp_erase_if_container(__c, __pred); } + typename unordered_multiset<_Value, _Hash, _Pred, _Alloc>::size_type + erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, + _Predicate __pred) { + return __libcpp_erase_if_container(__c, __pred); +} #endif template diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -261,9 +261,11 @@ noexcept(noexcept(x.swap(y))); template - void erase(vector& c, const U& value); // C++20 +typename vector::size_type +erase(vector& c, const U& value); // C++20 template - void erase_if(vector& c, Predicate pred); // C++20 +typename vector::size_type +erase_if(vector& c, Predicate pred); // C++20 } // std @@ -3389,14 +3391,24 @@ #if _LIBCPP_STD_VER > 17 template -inline _LIBCPP_INLINE_VISIBILITY -void erase(vector<_Tp, _Allocator>& __c, const _Up& __v) -{ __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end()); } +inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type +erase(vector<_Tp, _Allocator>& __c, const _Up& __v) { + auto __new_end = _VSTD::remove(__c.begin(), __c.end(), __v); + typename vector<_Tp, _Allocator>::size_type __erased_count = + std::distance(__new_end, __c.end()); + __c.erase(__new_end, __c.end()); + return __erased_count; +} template -inline _LIBCPP_INLINE_VISIBILITY -void erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) -{ __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end()); } +inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type +erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) { + auto __new_end = _VSTD::remove_if(__c.begin(), __c.end(), __pred); + typename vector<_Tp, _Allocator>::size_type __erased_count = + std::distance(__new_end, __c.end()); + __c.erase(__new_end, __c.end()); + return __erased_count; +} #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(map& c, Predicate pred); +// typename map::size_type +// erase_if(map& c, Predicate pred); #include @@ -29,13 +30,11 @@ } template -void -test0(Init vals, Pred p, Init expected) -{ - M s = make (vals); - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == make(expected)); +void test0(Init vals, Pred p, Init expected, size_t expected_erased_count) { + M s = make(vals); + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p); + assert(s == make(expected)); } template @@ -48,22 +47,22 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0({}, is1, {}); + test0({}, is1, {}, 0); - test0({1}, is1, {}); - test0({1}, is2, {1}); + test0({1}, is1, {}, 1); + test0({1}, is2, {1}, 0); - test0({1,2}, is1, {2}); - test0({1,2}, is2, {1}); - test0({1,2}, is3, {1,2}); + test0({1, 2}, is1, {2}, 1); + test0({1, 2}, is2, {1}, 1); + test0({1, 2}, is3, {1, 2}, 0); - test0({1,2,3}, is1, {2,3}); - test0({1,2,3}, is2, {1,3}); - test0({1,2,3}, is3, {1,2}); - test0({1,2,3}, is4, {1,2,3}); + test0({1, 2, 3}, is1, {2, 3}, 1); + test0({1, 2, 3}, is2, {1, 3}, 1); + test0({1, 2, 3}, is3, {1, 2}, 1); + test0({1, 2, 3}, is4, {1, 2, 3}, 0); - test0({1,2,3}, True, {}); - test0({1,2,3}, False, {1,2,3}); + test0({1, 2, 3}, True, {}, 3); + test0({1, 2, 3}, False, {1, 2, 3}, 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp @@ -9,8 +9,9 @@ // -// template -// void erase_if(multimap& c, Predicate pred); +// template +// typename multimap::size_type +// erase_if(multimap& c, Predicate pred); #include @@ -29,13 +30,11 @@ } template -void -test0(Init vals, Pred p, Init expected) -{ - M s = make (vals); - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == make(expected)); +void test0(Init vals, Pred p, Init expected, size_t expected_erased_count) { + M s = make(vals); + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == make(expected)); } template @@ -48,33 +47,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0({}, is1, {}); - - test0({1}, is1, {}); - test0({1}, is2, {1}); - - test0({1,2}, is1, {2}); - test0({1,2}, is2, {1}); - test0({1,2}, is3, {1,2}); - test0({1,1}, is1, {}); - test0({1,1}, is3, {1,1}); - - test0({1,2,3}, is1, {2,3}); - test0({1,2,3}, is2, {1,3}); - test0({1,2,3}, is3, {1,2}); - test0({1,2,3}, is4, {1,2,3}); - - test0({1,1,1}, is1, {}); - test0({1,1,1}, is2, {1,1,1}); - test0({1,1,2}, is1, {2}); - test0({1,1,2}, is2, {1,1}); - test0({1,1,2}, is3, {1,1,2}); - test0({1,2,2}, is1, {2,2}); - test0({1,2,2}, is2, {1}); - test0({1,2,2}, is3, {1,2,2}); - - test0({1,2,3}, True, {}); - test0({1,2,3}, False, {1,2,3}); + test0({}, is1, {}, 0); + + test0({1}, is1, {}, 1); + test0({1}, is2, {1}, 0); + + test0({1, 2}, is1, {2}, 1); + test0({1, 2}, is2, {1}, 1); + test0({1, 2}, is3, {1, 2}, 0); + test0({1, 1}, is1, {}, 2); + test0({1, 1}, is3, {1, 1}, 0); + + test0({1, 2, 3}, is1, {2, 3}, 1); + test0({1, 2, 3}, is2, {1, 3}, 1); + test0({1, 2, 3}, is3, {1, 2}, 1); + test0({1, 2, 3}, is4, {1, 2, 3}, 0); + + test0({1, 1, 1}, is1, {}, 3); + test0({1, 1, 1}, is2, {1, 1, 1}, 0); + test0({1, 1, 2}, is1, {2}, 2); + test0({1, 1, 2}, is2, {1, 1}, 1); + test0({1, 1, 2}, is3, {1, 1, 2}, 0); + test0({1, 2, 2}, is1, {2, 2}, 1); + test0({1, 2, 2}, is2, {1}, 2); + test0({1, 2, 2}, is3, {1, 2, 2}, 0); + + test0({1, 2, 3}, True, {}, 3); + test0({1, 2, 3}, False, {1, 2, 3}, 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(multiset& c, Predicate pred); +// typename multiset::size_type +// erase_if(multiset& c, Predicate pred); #include @@ -19,12 +20,10 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == expected); } template @@ -37,33 +36,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(), is1, S()); + test0(S(), is1, S(), 0); - test0(S({1}), is1, S()); - test0(S({1}), is2, S({1})); + test0(S({1}), is1, S(), 1); + test0(S({1}), is2, S({1}), 0); - test0(S({1,2}), is1, S({2})); - test0(S({1,2}), is2, S({1})); - test0(S({1,2}), is3, S({1,2})); - test0(S({1,1}), is1, S()); - test0(S({1,1}), is3, S({1,1})); + test0(S({1, 2}), is1, S({2}), 1); + test0(S({1, 2}), is2, S({1}), 1); + test0(S({1, 2}), is3, S({1, 2}), 0); + test0(S({1, 1}), is1, S(), 2); + test0(S({1, 1}), is3, S({1, 1}), 0); - test0(S({1,2,3}), is1, S({2,3})); - test0(S({1,2,3}), is2, S({1,3})); - test0(S({1,2,3}), is3, S({1,2})); - test0(S({1,2,3}), is4, S({1,2,3})); + test0(S({1, 2, 3}), is1, S({2, 3}), 1); + test0(S({1, 2, 3}), is2, S({1, 3}), 1); + test0(S({1, 2, 3}), is3, S({1, 2}), 1); + test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0); - test0(S({1,1,1}), is1, S()); - test0(S({1,1,1}), is2, S({1,1,1})); - test0(S({1,1,2}), is1, S({2})); - test0(S({1,1,2}), is2, S({1,1})); - test0(S({1,1,2}), is3, S({1,1,2})); - test0(S({1,2,2}), is1, S({2,2})); - test0(S({1,2,2}), is2, S({1})); - test0(S({1,2,2}), is3, S({1,2,2})); + test0(S({1, 1, 1}), is1, S(), 3); + test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), is1, S({2}), 2); + test0(S({1, 1, 2}), is2, S({1, 1}), 1); + test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), is1, S({2, 2}), 1); + test0(S({1, 2, 2}), is2, S({1}), 2); + test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0); - test0(S({1,2,3}), True, S()); - test0(S({1,2,3}), False, S({1,2,3})); + test0(S({1, 2, 3}), True, S(), 3); + test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(set& c, Predicate pred); +// typename set::size_type +// erase_if(set& c, Predicate pred); #include @@ -19,12 +20,10 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == expected); } template @@ -37,22 +36,22 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(), is1, S()); + test0(S(), is1, S(), 0); - test0(S({1}), is1, S()); - test0(S({1}), is2, S({1})); + test0(S({1}), is1, S(), 1); + test0(S({1}), is2, S({1}), 0); - test0(S({1,2}), is1, S({2})); - test0(S({1,2}), is2, S({1})); - test0(S({1,2}), is3, S({1,2})); + test0(S({1, 2}), is1, S({2}), 1); + test0(S({1, 2}), is2, S({1}), 1); + test0(S({1, 2}), is3, S({1, 2}), 0); - test0(S({1,2,3}), is1, S({2,3})); - test0(S({1,2,3}), is2, S({1,3})); - test0(S({1,2,3}), is3, S({1,2})); - test0(S({1,2,3}), is4, S({1,2,3})); + test0(S({1, 2, 3}), is1, S({2, 3}), 1); + test0(S({1, 2, 3}), is2, S({1, 3}), 1); + test0(S({1, 2, 3}), is3, S({1, 2}), 1); + test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0); - test0(S({1,2,3}), True, S()); - test0(S({1,2,3}), False, S({1,2,3})); + test0(S({1, 2, 3}), True, S(), 3); + test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp @@ -10,8 +10,8 @@ // // template -// void erase(deque& c, const U& value); - +// typename deque::size_type +// erase(deque& c, const U& value); #include #include @@ -21,49 +21,46 @@ #include "min_allocator.h" template -void -test0(S s, U val, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase(s, val))); - std::erase(s, val); - assert(s == expected); +void test0(S s, U val, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase(s, val))); + assert(expected_erased_count == std::erase(s, val)); + assert(s == expected); } template void test() { - - test0(S(), 1, S()); - - test0(S({1}), 1, S()); - test0(S({1}), 2, S({1})); - - test0(S({1,2}), 1, S({2})); - test0(S({1,2}), 2, S({1})); - test0(S({1,2}), 3, S({1,2})); - test0(S({1,1}), 1, S()); - test0(S({1,1}), 3, S({1,1})); - - test0(S({1,2,3}), 1, S({2,3})); - test0(S({1,2,3}), 2, S({1,3})); - test0(S({1,2,3}), 3, S({1,2})); - test0(S({1,2,3}), 4, S({1,2,3})); - - test0(S({1,1,1}), 1, S()); - test0(S({1,1,1}), 2, S({1,1,1})); - test0(S({1,1,2}), 1, S({2})); - test0(S({1,1,2}), 2, S({1,1})); - test0(S({1,1,2}), 3, S({1,1,2})); - test0(S({1,2,2}), 1, S({2,2})); - test0(S({1,2,2}), 2, S({1})); - test0(S({1,2,2}), 3, S({1,2,2})); - -// Test cross-type erasure - using opt = std::optional; - test0(S({1,2,1}), opt(), S({1,2,1})); - test0(S({1,2,1}), opt(1), S({2})); - test0(S({1,2,1}), opt(2), S({1,1})); - test0(S({1,2,1}), opt(3), S({1,2,1})); + test0(S(), 1, S(), 0); + + test0(S({1}), 1, S(), 1); + test0(S({1}), 2, S({1}), 0); + + test0(S({1, 2}), 1, S({2}), 1); + test0(S({1, 2}), 2, S({1}), 1); + test0(S({1, 2}), 3, S({1, 2}), 0); + test0(S({1, 1}), 1, S(), 2); + test0(S({1, 1}), 3, S({1, 1}), 0); + + test0(S({1, 2, 3}), 1, S({2, 3}), 1); + test0(S({1, 2, 3}), 2, S({1, 3}), 1); + test0(S({1, 2, 3}), 3, S({1, 2}), 1); + test0(S({1, 2, 3}), 4, S({1, 2, 3}), 0); + + test0(S({1, 1, 1}), 1, S(), 3); + test0(S({1, 1, 1}), 2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), 1, S({2}), 2); + test0(S({1, 1, 2}), 2, S({1, 1}), 1); + test0(S({1, 1, 2}), 3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), 1, S({2, 2}), 1); + test0(S({1, 2, 2}), 2, S({1}), 2); + test0(S({1, 2, 2}), 3, S({1, 2, 2}), 0); + + // Test cross-type erasure + using opt = std::optional; + test0(S({1, 2, 1}), opt(), S({1, 2, 1}), 0); + test0(S({1, 2, 1}), opt(1), S({2}), 2); + test0(S({1, 2, 1}), opt(2), S({1, 1}), 1); + test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(deque& c, Predicate pred); +// typename deque::size_type +// erase_if(deque& c, Predicate pred); #include @@ -19,12 +20,10 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == expected); } template @@ -37,33 +36,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(), is1, S()); + test0(S(), is1, S(), 0); - test0(S({1}), is1, S()); - test0(S({1}), is2, S({1})); + test0(S({1}), is1, S(), 1); + test0(S({1}), is2, S({1}), 0); - test0(S({1,2}), is1, S({2})); - test0(S({1,2}), is2, S({1})); - test0(S({1,2}), is3, S({1,2})); - test0(S({1,1}), is1, S()); - test0(S({1,1}), is3, S({1,1})); + test0(S({1, 2}), is1, S({2}), 1); + test0(S({1, 2}), is2, S({1}), 1); + test0(S({1, 2}), is3, S({1, 2}), 0); + test0(S({1, 1}), is1, S(), 2); + test0(S({1, 1}), is3, S({1, 1}), 0); - test0(S({1,2,3}), is1, S({2,3})); - test0(S({1,2,3}), is2, S({1,3})); - test0(S({1,2,3}), is3, S({1,2})); - test0(S({1,2,3}), is4, S({1,2,3})); + test0(S({1, 2, 3}), is1, S({2, 3}), 1); + test0(S({1, 2, 3}), is2, S({1, 3}), 1); + test0(S({1, 2, 3}), is3, S({1, 2}), 1); + test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0); - test0(S({1,1,1}), is1, S()); - test0(S({1,1,1}), is2, S({1,1,1})); - test0(S({1,1,2}), is1, S({2})); - test0(S({1,1,2}), is2, S({1,1})); - test0(S({1,1,2}), is3, S({1,1,2})); - test0(S({1,2,2}), is1, S({2,2})); - test0(S({1,2,2}), is2, S({1})); - test0(S({1,2,2}), is3, S({1,2,2})); + test0(S({1, 1, 1}), is1, S(), 3); + test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), is1, S({2}), 2); + test0(S({1, 1, 2}), is2, S({1, 1}), 1); + test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), is1, S({2, 2}), 1); + test0(S({1, 2, 2}), is2, S({1}), 2); + test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0); - test0(S({1,2,3}), True, S()); - test0(S({1,2,3}), False, S({1,2,3})); + test0(S({1, 2, 3}), True, S(), 3); + test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp --- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp +++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp @@ -10,8 +10,8 @@ // // template -// void erase(forward_list& c, const U& value); - +// typename forward_list::size_type +// erase(forward_list& c, const U& value); #include #include @@ -21,49 +21,46 @@ #include "min_allocator.h" template -void -test0(S s, U val, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase(s, val))); - std::erase(s, val); - assert(s == expected); +void test0(S s, U val, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase(s, val))); + assert(expected_erased_count == std::erase(s, val)); + assert(s == expected); } template void test() { - - test0(S(), 1, S()); - - test0(S({1}), 1, S()); - test0(S({1}), 2, S({1})); - - test0(S({1,2}), 1, S({2})); - test0(S({1,2}), 2, S({1})); - test0(S({1,2}), 3, S({1,2})); - test0(S({1,1}), 1, S()); - test0(S({1,1}), 3, S({1,1})); - - test0(S({1,2,3}), 1, S({2,3})); - test0(S({1,2,3}), 2, S({1,3})); - test0(S({1,2,3}), 3, S({1,2})); - test0(S({1,2,3}), 4, S({1,2,3})); - - test0(S({1,1,1}), 1, S()); - test0(S({1,1,1}), 2, S({1,1,1})); - test0(S({1,1,2}), 1, S({2})); - test0(S({1,1,2}), 2, S({1,1})); - test0(S({1,1,2}), 3, S({1,1,2})); - test0(S({1,2,2}), 1, S({2,2})); - test0(S({1,2,2}), 2, S({1})); - test0(S({1,2,2}), 3, S({1,2,2})); - -// Test cross-type erasure - using opt = std::optional; - test0(S({1,2,1}), opt(), S({1,2,1})); - test0(S({1,2,1}), opt(1), S({2})); - test0(S({1,2,1}), opt(2), S({1,1})); - test0(S({1,2,1}), opt(3), S({1,2,1})); + test0(S(), 1, S(), 0); + + test0(S({1}), 1, S(), 1); + test0(S({1}), 2, S({1}), 0); + + test0(S({1, 2}), 1, S({2}), 1); + test0(S({1, 2}), 2, S({1}), 1); + test0(S({1, 2}), 3, S({1, 2}), 0); + test0(S({1, 1}), 1, S(), 2); + test0(S({1, 1}), 3, S({1, 1}), 0); + + test0(S({1, 2, 3}), 1, S({2, 3}), 1); + test0(S({1, 2, 3}), 2, S({1, 3}), 1); + test0(S({1, 2, 3}), 3, S({1, 2}), 1); + test0(S({1, 2, 3}), 4, S({1, 2, 3}), 0); + + test0(S({1, 1, 1}), 1, S(), 3); + test0(S({1, 1, 1}), 2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), 1, S({2}), 2); + test0(S({1, 1, 2}), 2, S({1, 1}), 1); + test0(S({1, 1, 2}), 3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), 1, S({2, 2}), 1); + test0(S({1, 2, 2}), 2, S({1}), 2); + test0(S({1, 2, 2}), 3, S({1, 2, 2}), 0); + + // Test cross-type erasure + using opt = std::optional; + test0(S({1, 2, 1}), opt(), S({1, 2, 1}), 0); + test0(S({1, 2, 1}), opt(1), S({2}), 2); + test0(S({1, 2, 1}), opt(2), S({1, 1}), 1); + test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(forward_list& c, Predicate pred); +// typename forward_list::size_type +// erase_if(forward_list& c, Predicate pred); #include @@ -19,12 +20,10 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == expected); } template @@ -37,33 +36,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(), is1, S()); + test0(S(), is1, S(), 0); - test0(S({1}), is1, S()); - test0(S({1}), is2, S({1})); + test0(S({1}), is1, S(), 1); + test0(S({1}), is2, S({1}), 0); - test0(S({1,2}), is1, S({2})); - test0(S({1,2}), is2, S({1})); - test0(S({1,2}), is3, S({1,2})); - test0(S({1,1}), is1, S()); - test0(S({1,1}), is3, S({1,1})); + test0(S({1, 2}), is1, S({2}), 1); + test0(S({1, 2}), is2, S({1}), 1); + test0(S({1, 2}), is3, S({1, 2}), 0); + test0(S({1, 1}), is1, S(), 2); + test0(S({1, 1}), is3, S({1, 1}), 0); - test0(S({1,2,3}), is1, S({2,3})); - test0(S({1,2,3}), is2, S({1,3})); - test0(S({1,2,3}), is3, S({1,2})); - test0(S({1,2,3}), is4, S({1,2,3})); + test0(S({1, 2, 3}), is1, S({2, 3}), 1); + test0(S({1, 2, 3}), is2, S({1, 3}), 1); + test0(S({1, 2, 3}), is3, S({1, 2}), 1); + test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0); - test0(S({1,1,1}), is1, S()); - test0(S({1,1,1}), is2, S({1,1,1})); - test0(S({1,1,2}), is1, S({2})); - test0(S({1,1,2}), is2, S({1,1})); - test0(S({1,1,2}), is3, S({1,1,2})); - test0(S({1,2,2}), is1, S({2,2})); - test0(S({1,2,2}), is2, S({1})); - test0(S({1,2,2}), is3, S({1,2,2})); + test0(S({1, 1, 1}), is1, S(), 3); + test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), is1, S({2}), 2); + test0(S({1, 1, 2}), is2, S({1, 1}), 1); + test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), is1, S({2, 2}), 1); + test0(S({1, 2, 2}), is2, S({1}), 2); + test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0); - test0(S({1,2,3}), True, S()); - test0(S({1,2,3}), False, S({1,2,3})); + test0(S({1, 2, 3}), True, S(), 3); + test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/list/list.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/list/list.erasure/erase.pass.cpp --- a/libcxx/test/std/containers/sequences/list/list.erasure/erase.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/list.erasure/erase.pass.cpp @@ -10,8 +10,8 @@ // // template -// void erase(list& c, const U& value); - +// typename list::size_type +// erase(list& c, const U& value); #include #include @@ -21,49 +21,46 @@ #include "min_allocator.h" template -void -test0(S s, U val, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase(s, val))); - std::erase(s, val); - assert(s == expected); +void test0(S s, U val, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase(s, val))); + assert(expected_erased_count == std::erase(s, val)); + assert(s == expected); } template void test() { - - test0(S(), 1, S()); - - test0(S({1}), 1, S()); - test0(S({1}), 2, S({1})); - - test0(S({1,2}), 1, S({2})); - test0(S({1,2}), 2, S({1})); - test0(S({1,2}), 3, S({1,2})); - test0(S({1,1}), 1, S()); - test0(S({1,1}), 3, S({1,1})); - - test0(S({1,2,3}), 1, S({2,3})); - test0(S({1,2,3}), 2, S({1,3})); - test0(S({1,2,3}), 3, S({1,2})); - test0(S({1,2,3}), 4, S({1,2,3})); - - test0(S({1,1,1}), 1, S()); - test0(S({1,1,1}), 2, S({1,1,1})); - test0(S({1,1,2}), 1, S({2})); - test0(S({1,1,2}), 2, S({1,1})); - test0(S({1,1,2}), 3, S({1,1,2})); - test0(S({1,2,2}), 1, S({2,2})); - test0(S({1,2,2}), 2, S({1})); - test0(S({1,2,2}), 3, S({1,2,2})); - -// Test cross-type erasure - using opt = std::optional; - test0(S({1,2,1}), opt(), S({1,2,1})); - test0(S({1,2,1}), opt(1), S({2})); - test0(S({1,2,1}), opt(2), S({1,1})); - test0(S({1,2,1}), opt(3), S({1,2,1})); + test0(S(), 1, S(), 0); + + test0(S({1}), 1, S(), 1); + test0(S({1}), 2, S({1}), 0); + + test0(S({1, 2}), 1, S({2}), 1); + test0(S({1, 2}), 2, S({1}), 1); + test0(S({1, 2}), 3, S({1, 2}), 0); + test0(S({1, 1}), 1, S(), 2); + test0(S({1, 1}), 3, S({1, 1}), 0); + + test0(S({1, 2, 3}), 1, S({2, 3}), 1); + test0(S({1, 2, 3}), 2, S({1, 3}), 1); + test0(S({1, 2, 3}), 3, S({1, 2}), 1); + test0(S({1, 2, 3}), 4, S({1, 2, 3}), 0); + + test0(S({1, 1, 1}), 1, S(), 3); + test0(S({1, 1, 1}), 2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), 1, S({2}), 2); + test0(S({1, 1, 2}), 2, S({1, 1}), 1); + test0(S({1, 1, 2}), 3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), 1, S({2, 2}), 1); + test0(S({1, 2, 2}), 2, S({1}), 2); + test0(S({1, 2, 2}), 3, S({1, 2, 2}), 0); + + // Test cross-type erasure + using opt = std::optional; + test0(S({1, 2, 1}), opt(), S({1, 2, 1}), 0); + test0(S({1, 2, 1}), opt(1), S({2}), 2); + test0(S({1, 2, 1}), opt(2), S({1, 1}), 1); + test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(list& c, Predicate pred); +// typename list::size_type +// erase_if(list& c, Predicate pred); #include @@ -19,12 +20,10 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == expected); } template @@ -37,33 +36,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(), is1, S()); + test0(S(), is1, S(), 0); - test0(S({1}), is1, S()); - test0(S({1}), is2, S({1})); + test0(S({1}), is1, S(), 1); + test0(S({1}), is2, S({1}), 0); - test0(S({1,2}), is1, S({2})); - test0(S({1,2}), is2, S({1})); - test0(S({1,2}), is3, S({1,2})); - test0(S({1,1}), is1, S()); - test0(S({1,1}), is3, S({1,1})); + test0(S({1, 2}), is1, S({2}), 1); + test0(S({1, 2}), is2, S({1}), 1); + test0(S({1, 2}), is3, S({1, 2}), 0); + test0(S({1, 1}), is1, S(), 2); + test0(S({1, 1}), is3, S({1, 1}), 0); - test0(S({1,2,3}), is1, S({2,3})); - test0(S({1,2,3}), is2, S({1,3})); - test0(S({1,2,3}), is3, S({1,2})); - test0(S({1,2,3}), is4, S({1,2,3})); + test0(S({1, 2, 3}), is1, S({2, 3}), 1); + test0(S({1, 2, 3}), is2, S({1, 3}), 1); + test0(S({1, 2, 3}), is3, S({1, 2}), 1); + test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0); - test0(S({1,1,1}), is1, S()); - test0(S({1,1,1}), is2, S({1,1,1})); - test0(S({1,1,2}), is1, S({2})); - test0(S({1,1,2}), is2, S({1,1})); - test0(S({1,1,2}), is3, S({1,1,2})); - test0(S({1,2,2}), is1, S({2,2})); - test0(S({1,2,2}), is2, S({1})); - test0(S({1,2,2}), is3, S({1,2,2})); + test0(S({1, 1, 1}), is1, S(), 3); + test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), is1, S({2}), 2); + test0(S({1, 1, 2}), is2, S({1, 1}), 1); + test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), is1, S({2, 2}), 1); + test0(S({1, 2, 2}), is2, S({1}), 2); + test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0); - test0(S({1,2,3}), True, S()); - test0(S({1,2,3}), False, S({1,2,3})); + test0(S({1, 2, 3}), True, S(), 3); + test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp @@ -10,8 +10,8 @@ // // template -// void erase(vector& c, const U& value); - +// typename vector::size_type +// erase(vector& c, const U& value); #include #include @@ -21,49 +21,47 @@ #include "min_allocator.h" template -void -test0(S s, U val, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase(s, val))); - std::erase(s, val); - assert(s == expected); +void test0(S s, U val, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase(s, val))); + assert(expected_erased_count == std::erase(s, val)); + assert(s == expected); } template void test() { - test0(S(), 1, S()); - - test0(S({1}), 1, S()); - test0(S({1}), 2, S({1})); - - test0(S({1,2}), 1, S({2})); - test0(S({1,2}), 2, S({1})); - test0(S({1,2}), 3, S({1,2})); - test0(S({1,1}), 1, S()); - test0(S({1,1}), 3, S({1,1})); - - test0(S({1,2,3}), 1, S({2,3})); - test0(S({1,2,3}), 2, S({1,3})); - test0(S({1,2,3}), 3, S({1,2})); - test0(S({1,2,3}), 4, S({1,2,3})); - - test0(S({1,1,1}), 1, S()); - test0(S({1,1,1}), 2, S({1,1,1})); - test0(S({1,1,2}), 1, S({2})); - test0(S({1,1,2}), 2, S({1,1})); - test0(S({1,1,2}), 3, S({1,1,2})); - test0(S({1,2,2}), 1, S({2,2})); - test0(S({1,2,2}), 2, S({1})); - test0(S({1,2,2}), 3, S({1,2,2})); - -// Test cross-type erasure - using opt = std::optional; - test0(S({1,2,1}), opt(), S({1,2,1})); - test0(S({1,2,1}), opt(1), S({2})); - test0(S({1,2,1}), opt(2), S({1,1})); - test0(S({1,2,1}), opt(3), S({1,2,1})); + test0(S(), 1, S(), 0); + + test0(S({1}), 1, S(), 1); + test0(S({1}), 2, S({1}), 0); + + test0(S({1, 2}), 1, S({2}), 1); + test0(S({1, 2}), 2, S({1}), 1); + test0(S({1, 2}), 3, S({1, 2}), 0); + test0(S({1, 1}), 1, S(), 2); + test0(S({1, 1}), 3, S({1, 1}), 0); + + test0(S({1, 2, 3}), 1, S({2, 3}), 1); + test0(S({1, 2, 3}), 2, S({1, 3}), 1); + test0(S({1, 2, 3}), 3, S({1, 2}), 1); + test0(S({1, 2, 3}), 4, S({1, 2, 3}), 0); + + test0(S({1, 1, 1}), 1, S(), 3); + test0(S({1, 1, 1}), 2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), 1, S({2}), 2); + test0(S({1, 1, 2}), 2, S({1, 1}), 1); + test0(S({1, 1, 2}), 3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), 1, S({2, 2}), 1); + test0(S({1, 2, 2}), 2, S({1}), 2); + test0(S({1, 2, 2}), 3, S({1, 2, 2}), 0); + + // Test cross-type erasure + using opt = std::optional; + test0(S({1, 2, 1}), opt(), S({1, 2, 1}), 0); + test0(S({1, 2, 1}), opt(1), S({2}), 2); + test0(S({1, 2, 1}), opt(2), S({1, 1}), 1); + test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(vector& c, Predicate pred); +// typename vector::size_type +// erase_if(vector& c, Predicate pred); #include @@ -19,12 +20,10 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + assert(s == expected); } template @@ -37,33 +36,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(), is1, S()); + test0(S(), is1, S(), 0); - test0(S({1}), is1, S()); - test0(S({1}), is2, S({1})); + test0(S({1}), is1, S(), 1); + test0(S({1}), is2, S({1}), 0); - test0(S({1,2}), is1, S({2})); - test0(S({1,2}), is2, S({1})); - test0(S({1,2}), is3, S({1,2})); - test0(S({1,1}), is1, S()); - test0(S({1,1}), is3, S({1,1})); + test0(S({1, 2}), is1, S({2}), 1); + test0(S({1, 2}), is2, S({1}), 1); + test0(S({1, 2}), is3, S({1, 2}), 0); + test0(S({1, 1}), is1, S(), 2); + test0(S({1, 1}), is3, S({1, 1}), 0); - test0(S({1,2,3}), is1, S({2,3})); - test0(S({1,2,3}), is2, S({1,3})); - test0(S({1,2,3}), is3, S({1,2})); - test0(S({1,2,3}), is4, S({1,2,3})); + test0(S({1, 2, 3}), is1, S({2, 3}), 1); + test0(S({1, 2, 3}), is2, S({1, 3}), 1); + test0(S({1, 2, 3}), is3, S({1, 2}), 1); + test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0); - test0(S({1,1,1}), is1, S()); - test0(S({1,1,1}), is2, S({1,1,1})); - test0(S({1,1,2}), is1, S({2})); - test0(S({1,1,2}), is2, S({1,1})); - test0(S({1,1,2}), is3, S({1,1,2})); - test0(S({1,2,2}), is1, S({2,2})); - test0(S({1,2,2}), is2, S({1})); - test0(S({1,2,2}), is3, S({1,2,2})); + test0(S({1, 1, 1}), is1, S(), 3); + test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0); + test0(S({1, 1, 2}), is1, S({2}), 2); + test0(S({1, 1, 2}), is2, S({1, 1}), 1); + test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0); + test0(S({1, 2, 2}), is1, S({2, 2}), 1); + test0(S({1, 2, 2}), is2, S({1}), 2); + test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0); - test0(S({1,2,3}), True, S()); - test0(S({1,2,3}), False, S({1,2,3})); + test0(S({1, 2, 3}), True, S(), 3); + test0(S({1, 2, 3}), False, S({1, 2, 3}), 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/unord/unord.map/erase_if.pass.cpp b/libcxx/test/std/containers/unord/unord.map/erase_if.pass.cpp --- a/libcxx/test/std/containers/unord/unord.map/erase_if.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.map/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(unordered_map& c, Predicate pred); +// typename unordered_map::size_type +// erase_if(unordered_map& c, Predicate pred); #include @@ -29,14 +30,12 @@ } template -void -test0(Init vals, Pred p, Init expected) -{ - M s = make (vals); - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - M e = make(expected); - assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); +void test0(Init vals, Pred p, Init expected, size_t expected_erased_count) { + M s = make(vals); + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + M e = make(expected); + assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); } template @@ -49,22 +48,22 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0({}, is1, {}); + test0({}, is1, {}, 0); - test0({1}, is1, {}); - test0({1}, is2, {1}); + test0({1}, is1, {}, 1); + test0({1}, is2, {1}, 0); - test0({1,2}, is1, {2}); - test0({1,2}, is2, {1}); - test0({1,2}, is3, {1,2}); + test0({1, 2}, is1, {2}, 1); + test0({1, 2}, is2, {1}, 1); + test0({1, 2}, is3, {1, 2}, 0); - test0({1,2,3}, is1, {2,3}); - test0({1,2,3}, is2, {1,3}); - test0({1,2,3}, is3, {1,2}); - test0({1,2,3}, is4, {1,2,3}); + test0({1, 2, 3}, is1, {2, 3}, 1); + test0({1, 2, 3}, is2, {1, 3}, 1); + test0({1, 2, 3}, is3, {1, 2}, 1); + test0({1, 2, 3}, is4, {1, 2, 3}, 0); - test0({1,2,3}, True, {}); - test0({1,2,3}, False, {1,2,3}); + test0({1, 2, 3}, True, {}, 3); + test0({1, 2, 3}, False, {1, 2, 3}, 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/unord/unord.multimap/erase_if.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/erase_if.pass.cpp --- a/libcxx/test/std/containers/unord/unord.multimap/erase_if.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multimap/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(unordered_multimap& c, Predicate pred); +// typename unordered_multimap::size_type +// erase_if(unordered_multimap& c, Predicate pred); #include @@ -29,14 +30,12 @@ } template -void -test0(Init vals, Pred p, Init expected) -{ - M s = make (vals); - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - M e = make(expected); - assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); +void test0(Init vals, Pred p, Init expected, size_t expected_erased_count) { + M s = make(vals); + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + M e = make(expected); + assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); } template @@ -49,33 +48,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0({}, is1, {}); - - test0({1}, is1, {}); - test0({1}, is2, {1}); - - test0({1,2}, is1, {2}); - test0({1,2}, is2, {1}); - test0({1,2}, is3, {1,2}); - test0({1,1}, is1, {}); - test0({1,1}, is3, {1,1}); - - test0({1,2,3}, is1, {2,3}); - test0({1,2,3}, is2, {1,3}); - test0({1,2,3}, is3, {1,2}); - test0({1,2,3}, is4, {1,2,3}); - - test0({1,1,1}, is1, {}); - test0({1,1,1}, is2, {1,1,1}); - test0({1,1,2}, is1, {2}); - test0({1,1,2}, is2, {1,1}); - test0({1,1,2}, is3, {1,1,2}); - test0({1,2,2}, is1, {2,2}); - test0({1,2,2}, is2, {1}); - test0({1,2,2}, is3, {1,2,2}); - - test0({1,2,3}, True, {}); - test0({1,2,3}, False, {1,2,3}); + test0({}, is1, {}, 0); + + test0({1}, is1, {}, 1); + test0({1}, is2, {1}, 0); + + test0({1, 2}, is1, {2}, 1); + test0({1, 2}, is2, {1}, 1); + test0({1, 2}, is3, {1, 2}, 0); + test0({1, 1}, is1, {}, 2); + test0({1, 1}, is3, {1, 1}, 0); + + test0({1, 2, 3}, is1, {2, 3}, 1); + test0({1, 2, 3}, is2, {1, 3}, 1); + test0({1, 2, 3}, is3, {1, 2}, 1); + test0({1, 2, 3}, is4, {1, 2, 3}, 0); + + test0({1, 1, 1}, is1, {}, 3); + test0({1, 1, 1}, is2, {1, 1, 1}, 0); + test0({1, 1, 2}, is1, {2}, 2); + test0({1, 1, 2}, is2, {1, 1}, 1); + test0({1, 1, 2}, is3, {1, 1, 2}, 0); + test0({1, 2, 2}, is1, {2, 2}, 1); + test0({1, 2, 2}, is2, {1}, 2); + test0({1, 2, 2}, is3, {1, 2, 2}, 0); + + test0({1, 2, 3}, True, {}, 3); + test0({1, 2, 3}, False, {1, 2, 3}, 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/unord/unord.multiset/erase_if.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/erase_if.pass.cpp --- a/libcxx/test/std/containers/unord/unord.multiset/erase_if.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(unordered_multiset& c, Predicate pred); +// typename unordered_multiset::size_type +// erase_if(unordered_multiset& c, Predicate pred); #include @@ -30,14 +31,12 @@ } template -void -test0(Init vals, Pred p, Init expected) -{ - M s = make (vals); - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - M e = make(expected); - assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); +void test0(Init vals, Pred p, Init expected, size_t expected_erased_count) { + M s = make(vals); + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + M e = make(expected); + assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); } template @@ -50,33 +49,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0({}, is1, {}); - - test0({1}, is1, {}); - test0({1}, is2, {1}); - - test0({1,2}, is1, {2}); - test0({1,2}, is2, {1}); - test0({1,2}, is3, {1,2}); - test0({1,1}, is1, {}); - test0({1,1}, is3, {1,1}); - - test0({1,2,3}, is1, {2,3}); - test0({1,2,3}, is2, {1,3}); - test0({1,2,3}, is3, {1,2}); - test0({1,2,3}, is4, {1,2,3}); - - test0({1,1,1}, is1, {}); - test0({1,1,1}, is2, {1,1,1}); - test0({1,1,2}, is1, {2}); - test0({1,1,2}, is2, {1,1}); - test0({1,1,2}, is3, {1,1,2}); - test0({1,2,2}, is1, {2,2}); - test0({1,2,2}, is2, {1}); - test0({1,2,2}, is3, {1,2,2}); - - test0({1,2,3}, True, {}); - test0({1,2,3}, False, {1,2,3}); + test0({}, is1, {}, 0); + + test0({1}, is1, {}, 1); + test0({1}, is2, {1}, 0); + + test0({1, 2}, is1, {2}, 1); + test0({1, 2}, is2, {1}, 1); + test0({1, 2}, is3, {1, 2}, 0); + test0({1, 1}, is1, {}, 2); + test0({1, 1}, is3, {1, 1}, 0); + + test0({1, 2, 3}, is1, {2, 3}, 1); + test0({1, 2, 3}, is2, {1, 3}, 1); + test0({1, 2, 3}, is3, {1, 2}, 1); + test0({1, 2, 3}, is4, {1, 2, 3}, 0); + + test0({1, 1, 1}, is1, {}, 3); + test0({1, 1, 1}, is2, {1, 1, 1}, 0); + test0({1, 1, 2}, is1, {2}, 2); + test0({1, 1, 2}, is2, {1, 1}, 1); + test0({1, 1, 2}, is3, {1, 1, 2}, 0); + test0({1, 2, 2}, is1, {2, 2}, 1); + test0({1, 2, 2}, is2, {1}, 2); + test0({1, 2, 2}, is3, {1, 2, 2}, 0); + + test0({1, 2, 3}, True, {}, 3); + test0({1, 2, 3}, False, {1, 2, 3}, 0); } int main(int, char**) diff --git a/libcxx/test/std/containers/unord/unord.set/erase_if.pass.cpp b/libcxx/test/std/containers/unord/unord.set/erase_if.pass.cpp --- a/libcxx/test/std/containers/unord/unord.set/erase_if.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.set/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(unorderd_set& c, Predicate pred); +// typename unordered_set::size_type +// erase_if(unordered_set& c, Predicate pred); #include @@ -30,17 +31,14 @@ } template -void -test0(Init vals, Pred p, Init expected) -{ - M s = make (vals); - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - M e = make(expected); - assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); +void test0(Init vals, Pred p, Init expected, size_t expected_erased_count) { + M s = make(vals); + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + M e = make(expected); + assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end()))); } - template void test() { @@ -51,22 +49,22 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0({}, is1, {}); + test0({}, is1, {}, 0); - test0({1}, is1, {}); - test0({1}, is2, {1}); + test0({1}, is1, {}, 1); + test0({1}, is2, {1}, 0); - test0({1,2}, is1, {2}); - test0({1,2}, is2, {1}); - test0({1,2}, is3, {1,2}); + test0({1, 2}, is1, {2}, 1); + test0({1, 2}, is2, {1}, 1); + test0({1, 2}, is3, {1, 2}, 0); - test0({1,2,3}, is1, {2,3}); - test0({1,2,3}, is2, {1,3}); - test0({1,2,3}, is3, {1,2}); - test0({1,2,3}, is4, {1,2,3}); + test0({1, 2, 3}, is1, {2, 3}, 1); + test0({1, 2, 3}, is2, {1, 3}, 1); + test0({1, 2, 3}, is3, {1, 2}, 1); + test0({1, 2, 3}, is4, {1, 2, 3}, 0); - test0({1,2,3}, True, {}); - test0({1,2,3}, False, {1,2,3}); + test0({1, 2, 3}, True, {}, 3); + test0({1, 2, 3}, False, {1, 2, 3}, 0); } int main(int, char**) diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_nonmember_container_access 201411L [C++17] */ @@ -82,8 +82,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_nonmember_container_access diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_incomplete_container_elements 201505L [C++17] __cpp_lib_list_remove_return_type 201806L [C++2a] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -111,8 +111,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_incomplete_container_elements diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_incomplete_container_elements 201505L [C++17] __cpp_lib_list_remove_return_type 201806L [C++2a] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -111,8 +111,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_incomplete_container_elements diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_generic_associative_lookup 201304L [C++14] __cpp_lib_map_try_emplace 201411L [C++17] __cpp_lib_node_extract 201606L [C++17] @@ -133,8 +133,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_generic_associative_lookup diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_generic_associative_lookup 201304L [C++14] __cpp_lib_node_extract 201606L [C++17] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -117,8 +117,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_generic_associative_lookup diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp @@ -16,7 +16,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] __cpp_lib_char8_t 201811L [C++2a] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_nonmember_container_access 201411L [C++17] __cpp_lib_string_udls 201304L [C++14] __cpp_lib_string_view 201606L [C++17] @@ -143,8 +143,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_nonmember_container_access diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_generic_unordered_lookup 201811L [C++2a] __cpp_lib_node_extract 201606L [C++17] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -127,8 +127,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_generic_unordered_lookup 201811L [C++2a] __cpp_lib_node_extract 201606L [C++17] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -111,8 +111,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp @@ -15,7 +15,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L [C++17] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_incomplete_container_elements 201505L [C++17] __cpp_lib_nonmember_container_access 201411L [C++17] */ @@ -98,8 +98,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_incomplete_container_elements diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -38,7 +38,7 @@ __cpp_lib_destroying_delete 201806L [C++2a] __cpp_lib_enable_shared_from_this 201603L [C++17] __cpp_lib_endian 201907L [C++2a] - __cpp_lib_erase_if 201811L [C++2a] + __cpp_lib_erase_if 202002L [C++2a] __cpp_lib_exchange_function 201304L [C++14] __cpp_lib_execution 201603L [C++17] __cpp_lib_filesystem 201703L [C++17] @@ -1718,8 +1718,8 @@ # ifndef __cpp_lib_erase_if # error "__cpp_lib_erase_if should be defined in c++2a" # endif -# if __cpp_lib_erase_if != 201811L -# error "__cpp_lib_erase_if should have the value 201811L in c++2a" +# if __cpp_lib_erase_if != 202002L +# error "__cpp_lib_erase_if should have the value 202002L in c++2a" # endif # ifndef __cpp_lib_exchange_function diff --git a/libcxx/test/std/strings/strings.erasure/erase.pass.cpp b/libcxx/test/std/strings/strings.erasure/erase.pass.cpp --- a/libcxx/test/std/strings/strings.erasure/erase.pass.cpp +++ b/libcxx/test/std/strings/strings.erasure/erase.pass.cpp @@ -10,8 +10,8 @@ // // template -// void erase(basic_string& c, const U& value); - +// typename basic_string::size_type +// erase(basic_string& c, const U& value); #include #include @@ -21,50 +21,48 @@ #include "min_allocator.h" template -void -test0(S s, U val, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase(s, val))); - std::erase(s, val); - LIBCPP_ASSERT(s.__invariants()); - assert(s == expected); +void test0(S s, U val, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase(s, val))); + assert(expected_erased_count == std::erase(s, val)); + LIBCPP_ASSERT(s.__invariants()); + assert(s == expected); } template void test() { - test0(S(""), 'a', S("")); + test0(S(""), 'a', S(""), 0); - test0(S("a"), 'a', S("")); - test0(S("a"), 'b', S("a")); + test0(S("a"), 'a', S(""), 1); + test0(S("a"), 'b', S("a"), 0); - test0(S("ab"), 'a', S("b")); - test0(S("ab"), 'b', S("a")); - test0(S("ab"), 'c', S("ab")); - test0(S("aa"), 'a', S("")); - test0(S("aa"), 'c', S("aa")); + test0(S("ab"), 'a', S("b"), 1); + test0(S("ab"), 'b', S("a"), 1); + test0(S("ab"), 'c', S("ab"), 0); + test0(S("aa"), 'a', S(""), 2); + test0(S("aa"), 'c', S("aa"), 0); - test0(S("abc"), 'a', S("bc")); - test0(S("abc"), 'b', S("ac")); - test0(S("abc"), 'c', S("ab")); - test0(S("abc"), 'd', S("abc")); + test0(S("abc"), 'a', S("bc"), 1); + test0(S("abc"), 'b', S("ac"), 1); + test0(S("abc"), 'c', S("ab"), 1); + test0(S("abc"), 'd', S("abc"), 0); - test0(S("aab"), 'a', S("b")); - test0(S("aab"), 'b', S("aa")); - test0(S("aab"), 'c', S("aab")); - test0(S("abb"), 'a', S("bb")); - test0(S("abb"), 'b', S("a")); - test0(S("abb"), 'c', S("abb")); - test0(S("aaa"), 'a', S("")); - test0(S("aaa"), 'b', S("aaa")); + test0(S("aab"), 'a', S("b"), 2); + test0(S("aab"), 'b', S("aa"), 1); + test0(S("aab"), 'c', S("aab"), 0); + test0(S("abb"), 'a', S("bb"), 1); + test0(S("abb"), 'b', S("a"), 2); + test0(S("abb"), 'c', S("abb"), 0); + test0(S("aaa"), 'a', S(""), 3); + test0(S("aaa"), 'b', S("aaa"), 0); -// Test cross-type erasure - using opt = std::optional; - test0(S("aba"), opt(), S("aba")); - test0(S("aba"), opt('a'), S("b")); - test0(S("aba"), opt('b'), S("aa")); - test0(S("aba"), opt('c'), S("aba")); + // Test cross-type erasure + using opt = std::optional; + test0(S("aba"), opt(), S("aba"), 0); + test0(S("aba"), opt('a'), S("b"), 2); + test0(S("aba"), opt('b'), S("aa"), 1); + test0(S("aba"), opt('c'), S("aba"), 0); } int main(int, char**) diff --git a/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp b/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp --- a/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp @@ -10,7 +10,8 @@ // // template -// void erase_if(basic_string& c, Predicate pred); +// typename basic_string::size_type +// erase_if(basic_string& c, Predicate pred); #include @@ -19,13 +20,11 @@ #include "min_allocator.h" template -void -test0(S s, Pred p, S expected) -{ - ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p))); - std::erase_if(s, p); - LIBCPP_ASSERT(s.__invariants()); - assert(s == expected); +void test0(S s, Pred p, S expected, size_t expected_erased_count) { + ASSERT_SAME_TYPE(size_t, decltype(std::erase_if(s, p))); + assert(expected_erased_count == std::erase_if(s, p)); + LIBCPP_ASSERT(s.__invariants()); + assert(s == expected); } template @@ -38,33 +37,33 @@ auto True = [](auto) { return true; }; auto False = [](auto) { return false; }; - test0(S(""), isA, S("")); + test0(S(""), isA, S(""), 0); - test0(S("a"), isA, S("")); - test0(S("a"), isB, S("a")); + test0(S("a"), isA, S(""), 1); + test0(S("a"), isB, S("a"), 0); - test0(S("ab"), isA, S("b")); - test0(S("ab"), isB, S("a")); - test0(S("ab"), isC, S("ab")); - test0(S("aa"), isA, S("")); - test0(S("aa"), isC, S("aa")); + test0(S("ab"), isA, S("b"), 1); + test0(S("ab"), isB, S("a"), 1); + test0(S("ab"), isC, S("ab"), 0); + test0(S("aa"), isA, S(""), 2); + test0(S("aa"), isC, S("aa"), 0); - test0(S("abc"), isA, S("bc")); - test0(S("abc"), isB, S("ac")); - test0(S("abc"), isC, S("ab")); - test0(S("abc"), isD, S("abc")); + test0(S("abc"), isA, S("bc"), 1); + test0(S("abc"), isB, S("ac"), 1); + test0(S("abc"), isC, S("ab"), 1); + test0(S("abc"), isD, S("abc"), 0); - test0(S("aab"), isA, S("b")); - test0(S("aab"), isB, S("aa")); - test0(S("aab"), isC, S("aab")); - test0(S("abb"), isA, S("bb")); - test0(S("abb"), isB, S("a")); - test0(S("abb"), isC, S("abb")); - test0(S("aaa"), isA, S("")); - test0(S("aaa"), isB, S("aaa")); + test0(S("aab"), isA, S("b"), 2); + test0(S("aab"), isB, S("aa"), 1); + test0(S("aab"), isC, S("aab"), 0); + test0(S("abb"), isA, S("bb"), 1); + test0(S("abb"), isB, S("a"), 2); + test0(S("abb"), isC, S("abb"), 0); + test0(S("aaa"), isA, S(""), 3); + test0(S("aaa"), isB, S("aaa"), 0); - test0(S("aba"), False, S("aba")); - test0(S("aba"), True, S("")); + test0(S("aba"), False, S("aba"), 0); + test0(S("aba"), True, S(""), 3); } int main(int, char**) diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -475,7 +475,7 @@ }, {"name": "__cpp_lib_erase_if", "values": { - "c++2a": int(201811), + "c++2a": int(202002), }, "headers": ["string", "deque", "forward_list", "list", "vector", "map", "set", "unordered_map", "unordered_set"] @@ -588,7 +588,7 @@ }, {"name": "__cpp_lib_to_array", "values": { - "c++2a": 201907L, + "c++2a": int(201907), }, "headers": ["array"], }, diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -227,7 +227,7 @@ P0586LWGSafe integral comparisonsPrague P0593CWGImplicit creation of objects for low-level object manipulationPrague - P1115LWGImproving the Return Value of Erase-Like Algorithms II: Free erase/erase ifPrague + P1115LWGImproving the Return Value of Erase-Like Algorithms II: Free erase/erase ifPragueComplete11.0 P1243LWGRangify New AlgorithmsPrague P1460LWGMandating the Standard Library: Clause 20 - Utilities libraryPrague P1739LWGAvoid template bloat for safe_ranges in combination with "subrange-y" view adaptorsPrague