diff --git a/include/deque b/include/deque index c232e53c3..6f7d04be5 100644 --- a/include/deque +++ b/include/deque @@ -150,6 +150,11 @@ template 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 */ @@ -2928,6 +2933,19 @@ swap(deque<_Tp, _Allocator>& __x, deque<_Tp, _Allocator>& __y) __x.swap(__y); } +#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()); } + +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()); } +#endif + + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/include/forward_list b/include/forward_list index f9a71f033..b506acd1f 100644 --- a/include/forward_list +++ b/include/forward_list @@ -167,6 +167,11 @@ template 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,18 @@ swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) +{ __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; }); } +#endif + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/include/functional b/include/functional index bf3216f41..1fb44f271 100644 --- a/include/functional +++ b/include/functional @@ -2953,6 +2953,18 @@ template using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; #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; + } +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_FUNCTIONAL diff --git a/include/list b/include/list index 1a28c21ab..c69e31d93 100644 --- a/include/list +++ b/include/list @@ -169,6 +169,11 @@ template 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,18 @@ swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) +{ __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; }); } +#endif + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/include/map b/include/map index f6f2b6835..616bb46cf 100644 --- a/include/map +++ b/include/map @@ -254,6 +254,10 @@ void 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 @@ swap(multimap& x, multimap& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(multimap& c, Predicate pred); // C++20 + } // std */ @@ -1614,6 +1621,14 @@ swap(map<_Key, _Tp, _Compare, _Allocator>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + + template , class _Allocator = allocator > > class _LIBCPP_TEMPLATE_VIS multimap @@ -2151,6 +2166,13 @@ swap(multimap<_Key, _Tp, _Compare, _Allocator>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_MAP diff --git a/include/set b/include/set index fb15ecfa0..a0155f0b2 100644 --- a/include/set +++ b/include/set @@ -216,6 +216,9 @@ void 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 @@ void swap(multiset& x, multiset& y) noexcept(noexcept(x.swap(y))); +template + void erase_if(multiset& c, Predicate pred); // C++20 + } // std */ @@ -912,6 +918,13 @@ swap(set<_Key, _Compare, _Allocator>& __x, __x.swap(__y); } +#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); } +#endif + template , class _Allocator = allocator<_Key> > class _LIBCPP_TEMPLATE_VIS multiset @@ -1392,6 +1405,13 @@ swap(multiset<_Key, _Compare, _Allocator>& __x, __x.swap(__y); } +#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); } +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_SET diff --git a/include/string b/include/string index 4dd6ddc4e..fb838d1e5 100644 --- a/include/string +++ b/include/string @@ -437,6 +437,11 @@ template 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; @@ -4276,6 +4281,18 @@ getline(basic_istream<_CharT, _Traits>&& __is, #endif // _LIBCPP_CXX03_LANG +#if _LIBCPP_STD_VER > 17 +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()); } + +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()); } +#endif + #if _LIBCPP_DEBUG_LEVEL >= 2 template diff --git a/include/unordered_map b/include/unordered_map index 5dd923607..6035b05dc 100644 --- a/include/unordered_map +++ b/include/unordered_map @@ -384,6 +384,12 @@ template 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,13 @@ swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template bool operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, @@ -2243,6 +2256,13 @@ swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template bool operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, diff --git a/include/unordered_set b/include/unordered_set index 25b92203f..b4e61da89 100644 --- a/include/unordered_set +++ b/include/unordered_set @@ -339,6 +339,13 @@ template 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,13 @@ swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template bool operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, @@ -1497,6 +1511,13 @@ swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template bool operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, diff --git a/include/vector b/include/vector index 196ea70ea..edb6d3e09 100644 --- a/include/vector +++ b/include/vector @@ -261,6 +261,11 @@ template 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,18 @@ swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) __x.swap(__y); } +#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()); } + +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()); } +#endif + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/include/version b/include/version index 5e758fce7..552d663d0 100644 --- a/include/version +++ b/include/version @@ -39,6 +39,9 @@ __cpp_lib_complex_udls 201309L __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 @@ -118,6 +121,7 @@ __cpp_lib_void_t 201411L #if _LIBCPP_STD_VER > 17 #ifndef _LIBCPP_NO_HAS_CHAR8_T # define __cpp_lib_char8_t 201811L +#define __cpp_lib_erase_if 201811L #endif #endif diff --git a/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp b/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..f8cbc15d1 --- /dev/null +++ b/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>(); +} + diff --git a/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp b/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..8e786fdc9 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp b/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..3c619bb68 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp b/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..a55a38c2d --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp b/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp new file mode 100644 index 000000000..9a8c698a5 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp b/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..a090eb694 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp b/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp new file mode 100644 index 000000000..0163b8607 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp b/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..69685d2d3 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/list/list.erasure/erase.pass.cpp b/test/std/containers/sequences/list/list.erasure/erase.pass.cpp new file mode 100644 index 000000000..a9f65c053 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp b/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..99b1c6530 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp b/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp new file mode 100644 index 000000000..e88252f1d --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp b/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..8025a3407 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/unord/unord.map/erase_if.pass.cpp b/test/std/containers/unord/unord.map/erase_if.pass.cpp new file mode 100644 index 000000000..f6a580c21 --- /dev/null +++ b/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>(); +} + diff --git a/test/std/containers/unord/unord.multimap/erase_if.pass.cpp b/test/std/containers/unord/unord.multimap/erase_if.pass.cpp new file mode 100644 index 000000000..dc613269a --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/unord/unord.multiset/erase_if.pass.cpp b/test/std/containers/unord/unord.multiset/erase_if.pass.cpp new file mode 100644 index 000000000..7a9d93d43 --- /dev/null +++ b/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>(); +} diff --git a/test/std/containers/unord/unord.set/erase_if.pass.cpp b/test/std/containers/unord/unord.set/erase_if.pass.cpp new file mode 100644 index 000000000..e060fda1f --- /dev/null +++ b/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>(); +} diff --git a/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp index d3ca7d9b0..188d2f3c0 100644 --- a/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp +++ b/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 */ @@ -24,6 +25,16 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp index 73c8462ca..9b44f6e2c 100644 --- a/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp +++ b/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 @@ -26,6 +27,16 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp index 3db799563..e6e65655b 100644 --- a/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp +++ b/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 @@ -26,6 +27,16 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp index ffcc003e3..e7dbf7d20 100644 --- a/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp +++ b/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 @@ -27,6 +28,16 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp index 96918031d..716eae6d9 100644 --- a/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp +++ b/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 @@ -26,6 +27,16 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp index 2f408b988..87e8c8f96 100644 --- a/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp +++ b/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_char8_t 201811L __cpp_lib_nonmember_container_access 201411L __cpp_lib_string_udls 201304L @@ -27,6 +28,16 @@ int main() { // 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 TEST_STD_VER > 17 && defined(__cpp_char8_t) # if !defined(__cpp_lib_char8_t) LIBCPP_STATIC_ASSERT(false, "__cpp_lib_char8_t is not defined"); diff --git a/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp index 38e011717..d23a91a30 100644 --- a/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp +++ b/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 @@ -26,6 +27,17 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp index 762a07c37..c4dbed14b 100644 --- a/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp +++ b/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 @@ -25,6 +26,16 @@ int main() { // 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" diff --git a/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp b/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp index 9932a61c5..e7cb1942c 100644 --- a/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp +++ b/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 @@ -25,6 +26,16 @@ int main() { // 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" diff --git a/test/std/strings/strings.erasure/erase.pass.cpp b/test/std/strings/strings.erasure/erase.pass.cpp new file mode 100644 index 000000000..657a56c73 --- /dev/null +++ b/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>> (); +} diff --git a/test/std/strings/strings.erasure/erase_if.pass.cpp b/test/std/strings/strings.erasure/erase_if.pass.cpp new file mode 100644 index 000000000..d7014868f --- /dev/null +++ b/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>> (); +} diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 349d3c2bf..581191c76 100644 --- a/www/cxx2a_status.html +++ b/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