Index: include/deque =================================================================== --- include/deque +++ include/deque @@ -150,6 +150,11 @@ void swap(deque& x, deque& y) noexcept(noexcept(x.swap(y))); +template + void erase(deque& c, const U& value); // C++20 +template + void erase_if(deque& c, Predicate pred); // C++20 + } // std */ @@ -2927,6 +2932,17 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase(deque<_Tp, _Allocator>& __c, const _Up& __v) +{ __c.erase(remove(__c.begin(), __c.end(), __v), __c.end()); } + +template +void erase_if(deque<_Tp, _Allocator>& __c, _Predicate __pred) +{ __c.erase(remove_if(__c.begin(), __c.end(), __pred), __c.end()); } +#endif + + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS Index: include/forward_list =================================================================== --- include/forward_list +++ include/forward_list @@ -167,6 +167,11 @@ void swap(forward_list& x, forward_list& y) noexcept(noexcept(x.swap(y))); +template + void erase(forward_list& c, const U& value); // C++20 +template + void erase_if(forward_list& c, Predicate pred); // C++20 + } // std */ @@ -1744,6 +1749,16 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) +{ erase_if(__c, [&](auto& __elem) { return __elem == __v; }); } + +template +void erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) +{ __c.remove_if(__pred); } +#endif + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS Index: include/list =================================================================== --- include/list +++ include/list @@ -169,6 +169,11 @@ void swap(list& x, list& y) noexcept(noexcept(x.swap(y))); +template + void erase(list& c, const U& value); // C++20 +template + void erase_if(list& c, Predicate pred); // C++20 + } // std */ @@ -2450,6 +2455,16 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase(list<_Tp, _Allocator>& __c, const _Up& __v) +{ erase_if(__c, [&](auto& __elem) { return __elem == __v; }); } + +template +void erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) +{ __c.remove_if(__pred); } +#endif + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS Index: include/map =================================================================== --- include/map +++ include/map @@ -254,6 +254,10 @@ swap(map& x, map& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(map& c, Predicate pred); // C++20 + + template , class Allocator = allocator>> class multimap @@ -465,6 +469,9 @@ multimap& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(multimap& c, Predicate pred); // C++20 + } // std */ @@ -1614,6 +1621,21 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + + template , class _Allocator = allocator > > class _LIBCPP_TEMPLATE_VIS multimap @@ -2151,6 +2173,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_MAP Index: include/set =================================================================== --- include/set +++ include/set @@ -216,6 +216,9 @@ swap(set& x, set& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(set& c, Predicate pred); // C++20 + template , class Allocator = allocator> class multiset @@ -412,6 +415,9 @@ swap(multiset& x, multiset& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(multiset& c, Predicate pred); // C++20 + } // std */ @@ -912,6 +918,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + template , class _Allocator = allocator<_Key> > class _LIBCPP_TEMPLATE_VIS multiset @@ -1392,6 +1412,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_SET Index: include/string =================================================================== --- include/string +++ include/string @@ -437,6 +437,11 @@ basic_istream& getline(basic_istream& is, basic_string& str); +template +void erase(basic_string& c, const U& value); // C++20 +template +void erase_if(basic_string& c, Predicate pred); // C++20 + typedef basic_string string; typedef basic_string wstring; typedef basic_string u16string; @@ -4274,6 +4279,16 @@ #endif // _LIBCPP_CXX03_LANG +#if _LIBCPP_STD_VER > 17 +template +void erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) +{ __str.erase(remove(__str.begin(), __str.end(), __v), __str.end()); } + +template +void erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) +{ __str.erase(remove_if(__str.begin(), __str.end(), __pred), __str.end()); } +#endif + #if _LIBCPP_DEBUG_LEVEL >= 2 template Index: include/unordered_map =================================================================== --- include/unordered_map +++ include/unordered_map @@ -384,6 +384,12 @@ unordered_multimap& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(unordered_set& c, Predicate pred); // C++20 + +template + void erase_if(unordered_multiset& c, Predicate pred); // C++20 + template bool operator==(const unordered_multimap& x, @@ -1626,6 +1632,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + template bool operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, @@ -2243,6 +2263,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + template bool operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, Index: include/unordered_set =================================================================== --- include/unordered_set +++ include/unordered_set @@ -339,6 +339,13 @@ unordered_multiset& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(unordered_set& c, Predicate pred); // C++20 + +template + void erase_if(unordered_multiset& c, Predicate pred); // C++20 + + template bool operator==(const unordered_multiset& x, @@ -934,6 +941,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + template bool operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, @@ -1497,6 +1518,20 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ + for (auto __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} +#endif + template bool operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -261,6 +261,11 @@ void swap(vector& x, vector& y) noexcept(noexcept(x.swap(y))); +template + void erase(vector& c, const U& value); // C++20 +template + void erase_if(vector& c, Predicate pred); // C++20 + } // std */ @@ -3408,6 +3413,16 @@ __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +void erase(vector<_Tp, _Allocator>& __c, const _Up& __v) +{ __c.erase(remove(__c.begin(), __c.end(), __v), __c.end()); } + +template +void erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) +{ __c.erase(remove_if(__c.begin(), __c.end(), __pred), __c.end()); } +#endif + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS Index: include/version =================================================================== --- include/version +++ include/version @@ -37,6 +37,9 @@ __cpp_lib_concepts 201806L __cpp_lib_constexpr_swap_algorithms 201806L __cpp_lib_enable_shared_from_this 201603L +__cpp_lib_erase_if 201811L + + __cpp_lib_exchange_function 201304L __cpp_lib_execution 201603L __cpp_lib_filesystem 201703L @@ -114,6 +117,7 @@ #endif #if _LIBCPP_STD_VER > 17 +#define __cpp_lib_erase_if 201811L #endif #endif // _LIBCPP_VERSIONH Index: test/std/containers/associative/map/map.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/associative/map/map.erasure/erase_if.pass.cpp +++ test/std/containers/associative/map/map.erasure/erase_if.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(map& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "min_allocator.h" + +using Init = std::initializer_list; +template +M make (Init vals) +{ + M ret; + for (int v : vals) + ret[v] = v + 10; + return ret; +} + +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)); +} + +template +void test() +{ + auto is1 = [](auto v) { return v.first == 1;}; + auto is2 = [](auto v) { return v.first == 2;}; + auto is3 = [](auto v) { return v.first == 3;}; + auto is4 = [](auto v) { return v.first == 4;}; + 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,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}, True, {}); + test0({1,2,3}, False, {1,2,3}); +} + +int main() +{ + test>(); + test, min_allocator>>> (); + test, test_allocator>>> (); + + test>(); + test>(); +} + Index: test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp +++ test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(multimap& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "min_allocator.h" + +using Init = std::initializer_list; +template +M make (Init vals) +{ + M ret; + for (int v : vals) + ret.insert(typename M::value_type(v, v + 10)); + return ret; +} + +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)); +} + +template +void test() +{ + auto is1 = [](auto v) { return v.first == 1;}; + auto is2 = [](auto v) { return v.first == 2;}; + auto is3 = [](auto v) { return v.first == 3;}; + auto is4 = [](auto v) { return v.first == 4;}; + 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}); +} + +int main() +{ + test>(); + test, min_allocator>>> (); + test, test_allocator>>> (); + + test>(); + test>(); +} Index: test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp +++ test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(multiset& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(), is1, S()); + + test0(S({1}), is1, S()); + test0(S({1}), is2, S({1})); + + 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,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,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,2,3}), True, S()); + test0(S({1,2,3}), False, S({1,2,3})); +} + +int main() +{ + test>(); + test, min_allocator>> (); + test, test_allocator>> (); + + test>(); + test>(); +} Index: test/std/containers/associative/set/set.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/associative/set/set.erasure/erase_if.pass.cpp +++ test/std/containers/associative/set/set.erasure/erase_if.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(set& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(), is1, S()); + + test0(S({1}), is1, S()); + test0(S({1}), is2, S({1})); + + 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,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}), True, S()); + test0(S({1,2,3}), False, S({1,2,3})); +} + +int main() +{ + test>(); + test, min_allocator>> (); + test, test_allocator>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp =================================================================== --- test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp +++ test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase(deque& c, const U& value); + + +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +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})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp +++ test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(deque& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(), is1, S()); + + test0(S({1}), is1, S()); + test0(S({1}), is2, S({1})); + + 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,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,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,2,3}), True, S()); + test0(S({1,2,3}), False, S({1,2,3})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp +++ test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase(forward_list& c, const U& value); + + +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +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})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp +++ test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(forward_list& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(), is1, S()); + + test0(S({1}), is1, S()); + test0(S({1}), is2, S({1})); + + 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,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,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,2,3}), True, S()); + test0(S({1,2,3}), False, S({1,2,3})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/list/list.erasure/erase.pass.cpp =================================================================== --- test/std/containers/sequences/list/list.erasure/erase.pass.cpp +++ test/std/containers/sequences/list/list.erasure/erase.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase(list& c, const U& value); + + +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +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})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp +++ test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(list& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(), is1, S()); + + test0(S({1}), is1, S()); + test0(S({1}), is2, S({1})); + + 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,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,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,2,3}), True, S()); + test0(S({1,2,3}), False, S({1,2,3})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp =================================================================== --- test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp +++ test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase(vector& c, const U& value); + + +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +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})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp =================================================================== --- test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp +++ test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(vector& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(), is1, S()); + + test0(S({1}), is1, S()); + test0(S({1}), is2, S({1})); + + 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,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,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,2,3}), True, S()); + test0(S({1,2,3}), False, S({1,2,3})); +} + +int main() +{ + test>(); + test>> (); + test>> (); + + test>(); + test>(); +} Index: test/std/containers/unord/unord.map/erase_if.pass.cpp =================================================================== --- test/std/containers/unord/unord.map/erase_if.pass.cpp +++ test/std/containers/unord/unord.map/erase_if.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(unordered_map& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "min_allocator.h" + +using Init = std::initializer_list; +template +M make (Init vals) +{ + M ret; + for (int v : vals) + ret[v] = v + 10; + return ret; +} + +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()))); +} + +template +void test() +{ + auto is1 = [](auto v) { return v.first == 1;}; + auto is2 = [](auto v) { return v.first == 2;}; + auto is3 = [](auto v) { return v.first == 3;}; + auto is4 = [](auto v) { return v.first == 4;}; + 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,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}, True, {}); + test0({1,2,3}, False, {1,2,3}); +} + +int main() +{ + test>(); + test, std::equal_to, min_allocator>>> (); + test, std::equal_to, test_allocator>>> (); + + test>(); + test>(); +} + Index: test/std/containers/unord/unord.multimap/erase_if.pass.cpp =================================================================== --- test/std/containers/unord/unord.multimap/erase_if.pass.cpp +++ test/std/containers/unord/unord.multimap/erase_if.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(unordered_multimap& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "min_allocator.h" + +using Init = std::initializer_list; +template +M make (Init vals) +{ + M ret; + for (int v : vals) + ret.insert(typename M::value_type(v, v + 10)); + return ret; +} + +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()))); +} + +template +void test() +{ + auto is1 = [](auto v) { return v.first == 1;}; + auto is2 = [](auto v) { return v.first == 2;}; + auto is3 = [](auto v) { return v.first == 3;}; + auto is4 = [](auto v) { return v.first == 4;}; + 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}); +} + +int main() +{ + test>(); + test, std::equal_to, min_allocator>>> (); + test, std::equal_to, test_allocator>>> (); + + test>(); + test>(); +} Index: test/std/containers/unord/unord.multiset/erase_if.pass.cpp =================================================================== --- test/std/containers/unord/unord.multiset/erase_if.pass.cpp +++ test/std/containers/unord/unord.multiset/erase_if.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(unordered_multiset& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "min_allocator.h" + +using Init = std::initializer_list; + +template +M make (Init vals) +{ + M ret; + for (int v : vals) + ret.insert(v); + return ret; +} + +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()))); +} + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + 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}); +} + +int main() +{ + test>(); + test, std::equal_to, min_allocator>> (); + test, std::equal_to, test_allocator>> (); + + test>(); + test>(); +} Index: test/std/containers/unord/unord.set/erase_if.pass.cpp =================================================================== --- test/std/containers/unord/unord.set/erase_if.pass.cpp +++ test/std/containers/unord/unord.set/erase_if.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(unorderd_set& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "min_allocator.h" + +using Init = std::initializer_list; + +template +M make (Init vals) +{ + M ret; + for (int v : vals) + ret.insert(v); + return ret; +} + +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()))); +} + + +template +void test() +{ + auto is1 = [](auto v) { return v == 1;}; + auto is2 = [](auto v) { return v == 2;}; + auto is3 = [](auto v) { return v == 3;}; + auto is4 = [](auto v) { return v == 4;}; + 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,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}, True, {}); + test0({1,2,3}, False, {1,2,3}); +} + +int main() +{ + test>(); + test, std::equal_to, min_allocator>> (); + test, std::equal_to, test_allocator>> (); + + test>(); + test>(); +} Index: test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_nonmember_container_access 201411L */ @@ -23,6 +24,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_incomplete_container_elements 201505L __cpp_lib_list_remove_return_type 201806L __cpp_lib_nonmember_container_access 201411L @@ -25,6 +26,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_incomplete_container_elements 201505L __cpp_lib_list_remove_return_type 201806L __cpp_lib_nonmember_container_access 201411L @@ -25,6 +26,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_generic_associative_lookup 201304L __cpp_lib_map_try_emplace 201411L __cpp_lib_node_extract 201606L @@ -26,6 +27,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_generic_associative_lookup 201304L __cpp_lib_node_extract 201606L __cpp_lib_nonmember_container_access 201411L @@ -25,6 +26,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_nonmember_container_access 201411L __cpp_lib_string_udls 201304L __cpp_lib_string_view 201606L @@ -25,6 +26,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_node_extract 201606L __cpp_lib_nonmember_container_access 201411L __cpp_lib_unordered_map_try_emplace 201411L @@ -25,6 +26,17 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_node_extract 201606L __cpp_lib_nonmember_container_access 201411L @@ -24,6 +25,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp =================================================================== --- test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp +++ test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp @@ -12,6 +12,7 @@ /* Constant Value __cpp_lib_allocator_traits_is_always_equal 201411L + __cpp_lib_erase_if 201811L __cpp_lib_incomplete_container_elements 201505L __cpp_lib_nonmember_container_access 201411L @@ -24,6 +25,16 @@ { // ensure that the macros that are supposed to be defined in are defined. +#if TEST_STD_VER > 17 +# if !defined(__cpp_lib_erase_if) + LIBCPP_STATIC_ASSERT(false, "__cpp_lib_erase_if is not defined"); +# else +# if __cpp_lib_erase_if < 201811L +# error "__cpp_lib_erase_if has an invalid value" +# endif +# endif +#endif + /* #if !defined(__cpp_lib_fooby) # error "__cpp_lib_fooby is not defined" Index: test/std/strings/strings.erasure/erase.pass.cpp =================================================================== --- test/std/strings/strings.erasure/erase.pass.cpp +++ test/std/strings/strings.erasure/erase.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase(basic_string& c, const U& value); + + +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + + test0(S(""), 'a', S("")); + + test0(S("a"), 'a', S("")); + test0(S("a"), 'b', S("a")); + + 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("abc"), 'a', S("bc")); + test0(S("abc"), 'b', S("ac")); + test0(S("abc"), 'c', S("ab")); + test0(S("abc"), 'd', S("abc")); + + 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")); + +// 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")); +} + +int main() +{ + test(); + test, min_allocator>> (); + test, test_allocator>> (); +} Index: test/std/strings/strings.erasure/erase_if.pass.cpp =================================================================== --- test/std/strings/strings.erasure/erase_if.pass.cpp +++ test/std/strings/strings.erasure/erase_if.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// void erase_if(basic_string& c, Predicate pred); + +#include + +#include "test_macros.h" +#include "test_allocator.h" +#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); +} + +template +void test() +{ + auto isA = [](auto ch) { return ch == 'a';}; + auto isB = [](auto ch) { return ch == 'b';}; + auto isC = [](auto ch) { return ch == 'c';}; + auto isD = [](auto ch) { return ch == 'd';}; + auto True = [](auto) { return true; }; + auto False = [](auto) { return false; }; + + test0(S(""), isA, S("")); + + test0(S("a"), isA, S("")); + test0(S("a"), isB, S("a")); + + 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("abc"), isA, S("bc")); + test0(S("abc"), isB, S("ac")); + test0(S("abc"), isC, S("ab")); + test0(S("abc"), isD, S("abc")); + + 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("aba"), False, S("aba")); + test0(S("aba"), True, S("")); +} + +int main() +{ + test(); + test, min_allocator>> (); + test, test_allocator>> (); +} Index: www/cxx2a_status.html =================================================================== --- www/cxx2a_status.html +++ www/cxx2a_status.html @@ -131,7 +131,7 @@ P1123R0LWGEditorial Guidance for merging P0019r8 and P0528r3San Diego P1148R0LWGCleaning up Clause 20San Diego P1165R1LWGMake stateful allocator propagation more consistent for operator+(basic_string)San Diego - P1209R0LWGAdopt Consistent Container Erasure from Library Fundamentals 2 for C++20San Diego + P1209R0LWGAdopt Consistent Container Erasure from Library Fundamentals 2 for C++20San DiegoComplete8.0 P1210R0LWGCompleting the Rebase of Library Fundamentals, Version 3, Working DraftSan Diego P1236R1CWGAlternative Wording for P0907R4 Signed Integers are Two's ComplementSan Diego P1248R1LWGRemove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)San Diego