[libcxx] r349178 - Implement P1209 - Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20. Reviewed as https://reviews.llvm.org/D55532

Marshall Clow mclow.lists at gmail.com
Fri Dec 14 10:49:35 PST 2018


Author: marshall
Date: Fri Dec 14 10:49:35 2018
New Revision: 349178

URL: http://llvm.org/viewvc/llvm-project?rev=349178&view=rev
Log:
Implement P1209 - Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20. Reviewed as https://reviews.llvm.org/D55532

Added:
    libcxx/trunk/test/std/containers/associative/map/map.erasure/
    libcxx/trunk/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/associative/multimap/multimap.erasure/
    libcxx/trunk/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/associative/multiset/multiset.erasure/
    libcxx/trunk/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/associative/set/set.erasure/
    libcxx/trunk/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/
    libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp
    libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/
    libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp
    libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/sequences/list/list.erasure/
    libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase.pass.cpp
    libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/
    libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp
    libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.map/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.multimap/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.multiset/erase_if.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.set/erase_if.pass.cpp
    libcxx/trunk/test/std/strings/strings.erasure/
    libcxx/trunk/test/std/strings/strings.erasure/erase.pass.cpp
    libcxx/trunk/test/std/strings/strings.erasure/erase_if.pass.cpp
Modified:
    libcxx/trunk/include/deque
    libcxx/trunk/include/forward_list
    libcxx/trunk/include/functional
    libcxx/trunk/include/list
    libcxx/trunk/include/map
    libcxx/trunk/include/set
    libcxx/trunk/include/string
    libcxx/trunk/include/unordered_map
    libcxx/trunk/include/unordered_set
    libcxx/trunk/include/vector
    libcxx/trunk/include/version
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp
    libcxx/trunk/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp
    libcxx/trunk/www/cxx2a_status.html

Modified: libcxx/trunk/include/deque
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/deque?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/deque (original)
+++ libcxx/trunk/include/deque Fri Dec 14 10:49:35 2018
@@ -150,6 +150,11 @@ template <class T, class Allocator>
     void swap(deque<T,Allocator>& x, deque<T,Allocator>& y)
          noexcept(noexcept(x.swap(y)));
 
+template <class T, class Allocator, class U>
+    void erase(deque<T, Allocator>& c, const U& value);       // C++20
+template <class T, class Allocator, class Predicate>
+    void erase_if(deque<T, Allocator>& c, Predicate pred);    // C++20
+
 }  // std
 
 */
@@ -2928,6 +2933,19 @@ swap(deque<_Tp, _Allocator>& __x, deque<
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Tp, class _Allocator, class _Up>
+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 <class _Tp, class _Allocator, class _Predicate>
+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

Modified: libcxx/trunk/include/forward_list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/forward_list?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/forward_list (original)
+++ libcxx/trunk/include/forward_list Fri Dec 14 10:49:35 2018
@@ -167,6 +167,11 @@ template <class T, class Allocator>
     void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y)
          noexcept(noexcept(x.swap(y)));
 
+template <class T, class Allocator, class U>
+    void erase(forward_list<T, Allocator>& c, const U& value);       // C++20
+template <class T, class Allocator, class Predicate>
+    void erase_if(forward_list<T, Allocator>& c, Predicate pred);    // C++20
+
 }  // std
 
 */
@@ -1744,6 +1749,18 @@ swap(forward_list<_Tp, _Alloc>& __x, for
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Tp, class _Allocator, class _Predicate>
+inline _LIBCPP_INLINE_VISIBILITY
+void erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred)
+{ __c.remove_if(__pred); }
+
+template <class _Tp, class _Allocator, class _Up>
+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

Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Fri Dec 14 10:49:35 2018
@@ -2953,6 +2953,18 @@ template <class _Tp>
 using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type;
 #endif // > C++17
 
+template <class _Container, class _Predicate>
+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

Modified: libcxx/trunk/include/list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/list?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/list (original)
+++ libcxx/trunk/include/list Fri Dec 14 10:49:35 2018
@@ -169,6 +169,11 @@ template <class T, class Alloc>
     void swap(list<T,Alloc>& x, list<T,Alloc>& y)
          noexcept(noexcept(x.swap(y)));
 
+template <class T, class Allocator, class U>
+    void erase(list<T, Allocator>& c, const U& value);       // C++20
+template <class T, class Allocator, class Predicate>
+    void erase_if(list<T, Allocator>& c, Predicate pred);    // C++20
+
 }  // std
 
 */
@@ -2450,6 +2455,18 @@ swap(list<_Tp, _Alloc>& __x, list<_Tp, _
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Tp, class _Allocator, class _Predicate>
+inline _LIBCPP_INLINE_VISIBILITY
+void erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred)
+{ __c.remove_if(__pred); }
+
+template <class _Tp, class _Allocator, class _Up>
+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

Modified: libcxx/trunk/include/map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/map?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/map (original)
+++ libcxx/trunk/include/map Fri Dec 14 10:49:35 2018
@@ -254,6 +254,10 @@ void
 swap(map<Key, T, Compare, Allocator>& x, map<Key, T, Compare, Allocator>& y)
     noexcept(noexcept(x.swap(y)));
 
+template <class Key, class T, class Compare, class Allocator, class Predicate>
+  void erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
+
+
 template <class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
 class multimap
@@ -465,6 +469,9 @@ swap(multimap<Key, T, Compare, Allocator
      multimap<Key, T, Compare, Allocator>& y)
     noexcept(noexcept(x.swap(y)));
 
+template <class Key, class T, class Compare, class Allocator, class Predicate>
+  void erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
+
 }  // std
 
 */
@@ -1614,6 +1621,14 @@ swap(map<_Key, _Tp, _Compare, _Allocator
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate>
+inline _LIBCPP_INLINE_VISIBILITY
+void erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred)
+{ __libcpp_erase_if_container(__c, __pred); }
+#endif
+
+
 template <class _Key, class _Tp, class _Compare = less<_Key>,
           class _Allocator = allocator<pair<const _Key, _Tp> > >
 class _LIBCPP_TEMPLATE_VIS multimap
@@ -2151,6 +2166,13 @@ swap(multimap<_Key, _Tp, _Compare, _Allo
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate>
+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

Modified: libcxx/trunk/include/set
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/set?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/set (original)
+++ libcxx/trunk/include/set Fri Dec 14 10:49:35 2018
@@ -216,6 +216,9 @@ void
 swap(set<Key, Compare, Allocator>& x, set<Key, Compare, Allocator>& y)
     noexcept(noexcept(x.swap(y)));
 
+template <class Key, class Compare, class Allocator, class Predicate>
+  void erase_if(set<Key, Compare, Allocator>& c, Predicate pred);  // C++20
+
 template <class Key, class Compare = less<Key>,
           class Allocator = allocator<Key>>
 class multiset
@@ -412,6 +415,9 @@ void
 swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y)
     noexcept(noexcept(x.swap(y)));
 
+template <class Key, class Compare, class Allocator, class Predicate>
+  void erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);  // C++20
+
 }  // std
 
 */
@@ -912,6 +918,13 @@ swap(set<_Key, _Compare, _Allocator>& __
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Key, class _Compare, class _Allocator, class _Predicate>
+inline _LIBCPP_INLINE_VISIBILITY
+void erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred)
+{ __libcpp_erase_if_container(__c, __pred); }
+#endif
+
 template <class _Key, class _Compare = less<_Key>,
           class _Allocator = allocator<_Key> >
 class _LIBCPP_TEMPLATE_VIS multiset
@@ -1392,6 +1405,13 @@ swap(multiset<_Key, _Compare, _Allocator
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Key, class _Compare, class _Allocator, class _Predicate>
+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

Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Fri Dec 14 10:49:35 2018
@@ -437,6 +437,11 @@ template<class charT, class traits, clas
 basic_istream<charT, traits>&
 getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
 
+template<class charT, class traits, class Allocator, class U>
+void erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20
+template<class charT, class traits, class Allocator, class Predicate>
+void erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20
+
 typedef basic_string<char>    string;
 typedef basic_string<wchar_t> wstring;
 typedef basic_string<char16_t> u16string;
@@ -4276,6 +4281,18 @@ getline(basic_istream<_CharT, _Traits>&&
 
 #endif  // _LIBCPP_CXX03_LANG
 
+#if _LIBCPP_STD_VER > 17
+template<class _CharT, class _Traits, class _Allocator, class _Up>
+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<class _CharT, class _Traits, class _Allocator, class _Predicate>
+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<class _CharT, class _Traits, class _Allocator>

Modified: libcxx/trunk/include/unordered_map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/unordered_map?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/unordered_map (original)
+++ libcxx/trunk/include/unordered_map Fri Dec 14 10:49:35 2018
@@ -384,6 +384,12 @@ template <class Key, class T, class Hash
               unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
               noexcept(noexcept(x.swap(y)));
 
+template <class K, class T, class H, class P, class A, class Predicate>
+    void erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred);       // C++20
+
+template <class K, class T, class H, class P, class A, class Predicate>
+    void erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred);  // C++20
+
 template <class Key, class T, class Hash, class Pred, class Alloc>
     bool
     operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
@@ -1626,6 +1632,13 @@ swap(unordered_map<_Key, _Tp, _Hash, _Pr
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate>
+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 <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
 bool
 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
@@ -2243,6 +2256,13 @@ swap(unordered_multimap<_Key, _Tp, _Hash
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate>
+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 <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
 bool
 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,

Modified: libcxx/trunk/include/unordered_set
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/unordered_set?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/unordered_set (original)
+++ libcxx/trunk/include/unordered_set Fri Dec 14 10:49:35 2018
@@ -339,6 +339,13 @@ template <class Value, class Hash, class
               unordered_multiset<Value, Hash, Pred, Alloc>& y)
               noexcept(noexcept(x.swap(y)));
 
+template <class K, class T, class H, class P, class A, class Predicate>
+    void erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred);       // C++20
+
+template <class K, class T, class H, class P, class A, class Predicate>
+    void erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred);  // C++20
+
+
 template <class Value, class Hash, class Pred, class Alloc>
     bool
     operator==(const unordered_multiset<Value, Hash, Pred, Alloc>& x,
@@ -934,6 +941,13 @@ swap(unordered_set<_Value, _Hash, _Pred,
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate>
+inline _LIBCPP_INLINE_VISIBILITY
+void erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred)
+{ __libcpp_erase_if_container(__c, __pred); }
+#endif
+
 template <class _Value, class _Hash, class _Pred, class _Alloc>
 bool
 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
@@ -1497,6 +1511,13 @@ swap(unordered_multiset<_Value, _Hash, _
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate>
+inline _LIBCPP_INLINE_VISIBILITY
+void erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred)
+{ __libcpp_erase_if_container(__c, __pred); }
+#endif
+
 template <class _Value, class _Hash, class _Pred, class _Alloc>
 bool
 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,

Modified: libcxx/trunk/include/vector
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/vector?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/vector (original)
+++ libcxx/trunk/include/vector Fri Dec 14 10:49:35 2018
@@ -261,6 +261,11 @@ template <class T, class Allocator>
 void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
     noexcept(noexcept(x.swap(y)));
 
+template <class T, class Allocator, class U>
+    void erase(vector<T, Allocator>& c, const U& value);       // C++20
+template <class T, class Allocator, class Predicate>
+    void erase_if(vector<T, Allocator>& c, Predicate pred);    // C++20
+
 }  // std
 
 */
@@ -3408,6 +3413,18 @@ swap(vector<_Tp, _Allocator>& __x, vecto
     __x.swap(__y);
 }
 
+#if _LIBCPP_STD_VER > 17
+template <class _Tp, class _Allocator, class _Up>
+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 <class _Tp, class _Allocator, class _Predicate>
+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

Modified: libcxx/trunk/include/version
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/version?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/include/version (original)
+++ libcxx/trunk/include/version Fri Dec 14 10:49:35 2018
@@ -39,6 +39,9 @@ __cpp_lib_complex_udls
 __cpp_lib_concepts                          201806L <concepts>
 __cpp_lib_constexpr_swap_algorithms         201806L <algorithm>
 __cpp_lib_enable_shared_from_this           201603L <memory>
+__cpp_lib_erase_if                          201811L <string> <deque> <forward_list> <list> 
+                                                    <vector> <map> <set> <unordered_map> 
+                                                    <unordered_set>
 __cpp_lib_exchange_function                 201304L <utility>
 __cpp_lib_execution                         201603L <execution>
 __cpp_lib_filesystem                        201703L <filesystem>
@@ -118,6 +121,7 @@ __cpp_lib_void_t
 #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
 

Added: libcxx/trunk/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <map>
+
+// template <class Key, class T, class Compare, class Allocator, class Predicate>
+//   void erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);
+
+#include <map>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+using Init = std::initializer_list<int>;
+template <typename M>
+M make (Init vals)
+{
+    M ret;
+    for (int v : vals)
+        ret[v] = v + 10;
+    return ret;
+}
+
+template <typename M, typename Pred>
+void
+test0(Init vals, Pred p, Init expected)
+{
+    M s = make<M> (vals);
+    ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p)));
+    std::erase_if(s, p);
+    assert(s == make<M>(expected));
+}
+
+template <typename S>
+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<S>({}, is1, {});
+
+    test0<S>({1}, is1, {});
+    test0<S>({1}, is2, {1});
+
+    test0<S>({1,2}, is1, {2});
+    test0<S>({1,2}, is2, {1});
+    test0<S>({1,2}, is3, {1,2});
+
+    test0<S>({1,2,3}, is1, {2,3});
+    test0<S>({1,2,3}, is2, {1,3});
+    test0<S>({1,2,3}, is3, {1,2});
+    test0<S>({1,2,3}, is4, {1,2,3});
+
+    test0<S>({1,2,3}, True,  {});
+    test0<S>({1,2,3}, False, {1,2,3});
+}
+
+int main()
+{
+    test<std::map<int, int>>();
+    test<std::map<int, int, std::less<int>, min_allocator<std::pair<const int, int>>>> ();
+    test<std::map<int, int, std::less<int>, test_allocator<std::pair<const int, int>>>> ();
+
+    test<std::map<long, short>>();
+    test<std::map<short, double>>();
+}
+

Added: libcxx/trunk/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/multimap/multimap.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <map>
+
+//   template <class Key, class T, class Compare, class Allocator, class Predicate>
+//     void erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);
+
+#include <map>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+using Init = std::initializer_list<int>;
+template <typename M>
+M make (Init vals)
+{
+    M ret;
+    for (int v : vals)
+        ret.insert(typename M::value_type(v, v + 10));
+    return ret;
+}
+
+template <typename M, typename Pred>
+void
+test0(Init vals, Pred p, Init expected)
+{
+    M s = make<M> (vals);
+    ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p)));
+    std::erase_if(s, p);
+    assert(s == make<M>(expected));
+}
+
+template <typename S>
+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<S>({}, is1, {});
+
+    test0<S>({1}, is1, {});
+    test0<S>({1}, is2, {1});
+
+    test0<S>({1,2}, is1, {2});
+    test0<S>({1,2}, is2, {1});
+    test0<S>({1,2}, is3, {1,2});
+    test0<S>({1,1}, is1, {});
+    test0<S>({1,1}, is3, {1,1});
+
+    test0<S>({1,2,3}, is1, {2,3});
+    test0<S>({1,2,3}, is2, {1,3});
+    test0<S>({1,2,3}, is3, {1,2});
+    test0<S>({1,2,3}, is4, {1,2,3});
+
+    test0<S>({1,1,1}, is1, {});
+    test0<S>({1,1,1}, is2, {1,1,1});
+    test0<S>({1,1,2}, is1, {2});
+    test0<S>({1,1,2}, is2, {1,1});
+    test0<S>({1,1,2}, is3, {1,1,2});
+    test0<S>({1,2,2}, is1, {2,2});
+    test0<S>({1,2,2}, is2, {1});
+    test0<S>({1,2,2}, is3, {1,2,2});
+    
+    test0<S>({1,2,3}, True,  {});
+    test0<S>({1,2,3}, False, {1,2,3});
+}
+
+int main()
+{
+    test<std::multimap<int, int>>();
+    test<std::multimap<int, int, std::less<int>, min_allocator<std::pair<const int, int>>>> ();
+    test<std::multimap<int, int, std::less<int>, test_allocator<std::pair<const int, int>>>> ();
+
+    test<std::multimap<long, short>>();
+    test<std::multimap<short, double>>();
+}

Added: libcxx/trunk/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/multiset/multiset.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <set>
+
+// template <class T, class Compare, class Allocator, class Predicate>
+//   void erase_if(multiset<T, Compare, Allocator>& c, Predicate pred);
+
+#include <set>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::multiset<int>>();
+    test<std::multiset<int, std::less<int>, min_allocator<int>>> ();
+    test<std::multiset<int, std::less<int>, test_allocator<int>>> ();
+
+    test<std::multiset<long>>();
+    test<std::multiset<double>>();
+}

Added: libcxx/trunk/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/associative/set/set.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <set>
+
+// template <class T, class Compare, class Allocator, class Predicate>
+//   void erase_if(set<T, Compare, Allocator>& c, Predicate pred);
+
+#include <set>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::set<int>>();
+    test<std::set<int, std::less<int>, min_allocator<int>>> ();
+    test<std::set<int, std::less<int>, test_allocator<int>>> ();
+
+    test<std::set<long>>();
+    test<std::set<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <deque>
+
+// template <class T, class Allocator, class U>
+//   void erase(deque<T, Allocator>& c, const U& value);
+  
+
+#include <deque>
+#include <optional>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class U>
+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 <class S>
+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<typename S::value_type>;
+    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<std::deque<int>>();
+    test<std::deque<int, min_allocator<int>>> ();
+    test<std::deque<int, test_allocator<int>>> ();
+
+    test<std::deque<long>>();
+    test<std::deque<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <deque>
+
+// template <class T, class Allocator, class Predicate>
+//   void erase_if(deque<T, Allocator>& c, Predicate pred);  
+
+#include <deque>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::deque<int>>();
+    test<std::deque<int, min_allocator<int>>> ();
+    test<std::deque<int, test_allocator<int>>> ();
+
+    test<std::deque<long>>();
+    test<std::deque<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <forward_list>
+
+// template <class T, class Allocator, class U>
+//   void erase(forward_list<T, Allocator>& c, const U& value);
+  
+
+#include <forward_list>
+#include <optional>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class U>
+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 <class S>
+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<typename S::value_type>;
+    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<std::forward_list<int>>();
+    test<std::forward_list<int, min_allocator<int>>> ();
+    test<std::forward_list<int, test_allocator<int>>> ();
+
+    test<std::forward_list<long>>();
+    test<std::forward_list<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <forward_list>
+
+// template <class T, class Allocator, class Predicate>
+//   void erase_if(forward_list<T, Allocator>& c, Predicate pred);  
+
+#include <forward_list>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::forward_list<int>>();
+    test<std::forward_list<int, min_allocator<int>>> ();
+    test<std::forward_list<int, test_allocator<int>>> ();
+
+    test<std::forward_list<long>>();
+    test<std::forward_list<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <list>
+
+// template <class T, class Allocator, class U>
+//   void erase(list<T, Allocator>& c, const U& value);
+  
+
+#include <list>
+#include <optional>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class U>
+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 <class S>
+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<typename S::value_type>;
+    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<std::list<int>>();
+    test<std::list<int, min_allocator<int>>> ();
+    test<std::list<int, test_allocator<int>>> ();
+
+    test<std::list<long>>();
+    test<std::list<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/list/list.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <list>
+
+// template <class T, class Allocator, class Predicate>
+//   void erase_if(list<T, Allocator>& c, Predicate pred);  
+
+#include <list>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::list<int>>();
+    test<std::list<int, min_allocator<int>>> ();
+    test<std::list<int, test_allocator<int>>> ();
+
+    test<std::list<long>>();
+    test<std::list<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <vector>
+
+// template <class T, class Allocator, class U>
+//   void erase(vector<T, Allocator>& c, const U& value);
+  
+
+#include <vector>
+#include <optional>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class U>
+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 <class S>
+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<typename S::value_type>;
+    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<std::vector<int>>();
+    test<std::vector<int, min_allocator<int>>> ();
+    test<std::vector<int, test_allocator<int>>> ();
+
+    test<std::vector<long>>();
+    test<std::vector<double>>();
+}

Added: libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/sequences/vector/vector.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <vector>
+
+// template <class T, class Allocator, class Predicate>
+//   void erase_if(vector<T, Allocator>& c, Predicate pred);  
+
+#include <vector>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::vector<int>>();
+    test<std::vector<int, min_allocator<int>>> ();
+    test<std::vector<int, test_allocator<int>>> ();
+
+    test<std::vector<long>>();
+    test<std::vector<double>>();
+}

Added: libcxx/trunk/test/std/containers/unord/unord.map/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.map/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.map/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.map/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <unordered_map>
+
+// template <class Key, class T, class Hash, class Pred, class Allocator, class Predicate>
+//   void erase_if(unordered_map<Key, T, Hash, Pred, Allocator>& c, Predicate pred);
+
+#include <unordered_map>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+using Init = std::initializer_list<int>;
+template <typename M>
+M make (Init vals)
+{
+    M ret;
+    for (int v : vals)
+        ret[v] = v + 10;
+    return ret;
+}
+
+template <typename M, typename Pred>
+void
+test0(Init vals, Pred p, Init expected)
+{
+    M s = make<M> (vals);
+    ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p)));
+    std::erase_if(s, p);
+    M e = make<M>(expected);
+    assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end())));
+}
+
+template <typename S>
+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<S>({}, is1, {});
+
+    test0<S>({1}, is1, {});
+    test0<S>({1}, is2, {1});
+
+    test0<S>({1,2}, is1, {2});
+    test0<S>({1,2}, is2, {1});
+    test0<S>({1,2}, is3, {1,2});
+
+    test0<S>({1,2,3}, is1, {2,3});
+    test0<S>({1,2,3}, is2, {1,3});
+    test0<S>({1,2,3}, is3, {1,2});
+    test0<S>({1,2,3}, is4, {1,2,3});
+
+    test0<S>({1,2,3}, True,  {});
+    test0<S>({1,2,3}, False, {1,2,3});
+}
+
+int main()
+{
+    test<std::unordered_map<int, int>>();
+    test<std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, min_allocator<std::pair<const int, int>>>> ();
+    test<std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int, int>>>> ();
+
+    test<std::unordered_map<long, short>>();
+    test<std::unordered_map<short, double>>();
+}
+

Added: libcxx/trunk/test/std/containers/unord/unord.multimap/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.multimap/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.multimap/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.multimap/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <unordered_map>
+
+// template <class Key, class T, class Hash, class Pred, class Allocator, class Predicate>
+//   void erase_if(unordered_multimap<Key, T, Hash, Pred, Allocator>& c, Predicate pred);
+
+#include <unordered_map>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+using Init = std::initializer_list<int>;
+template <typename M>
+M make (Init vals)
+{
+    M ret;
+    for (int v : vals)
+        ret.insert(typename M::value_type(v, v + 10));
+    return ret;
+}
+
+template <typename M, typename Pred>
+void
+test0(Init vals, Pred p, Init expected)
+{
+    M s = make<M> (vals);
+    ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p)));
+    std::erase_if(s, p);
+    M e = make<M>(expected);
+    assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end())));
+}
+
+template <typename S>
+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<S>({}, is1, {});
+
+    test0<S>({1}, is1, {});
+    test0<S>({1}, is2, {1});
+
+    test0<S>({1,2}, is1, {2});
+    test0<S>({1,2}, is2, {1});
+    test0<S>({1,2}, is3, {1,2});
+    test0<S>({1,1}, is1, {});
+    test0<S>({1,1}, is3, {1,1});
+
+    test0<S>({1,2,3}, is1, {2,3});
+    test0<S>({1,2,3}, is2, {1,3});
+    test0<S>({1,2,3}, is3, {1,2});
+    test0<S>({1,2,3}, is4, {1,2,3});
+
+    test0<S>({1,1,1}, is1, {});
+    test0<S>({1,1,1}, is2, {1,1,1});
+    test0<S>({1,1,2}, is1, {2});
+    test0<S>({1,1,2}, is2, {1,1});
+    test0<S>({1,1,2}, is3, {1,1,2});
+    test0<S>({1,2,2}, is1, {2,2});
+    test0<S>({1,2,2}, is2, {1});
+    test0<S>({1,2,2}, is3, {1,2,2});
+    
+    test0<S>({1,2,3}, True,  {});
+    test0<S>({1,2,3}, False, {1,2,3});
+}
+
+int main()
+{
+    test<std::unordered_multimap<int, int>>();
+    test<std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, min_allocator<std::pair<const int, int>>>> ();
+    test<std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, test_allocator<std::pair<const int, int>>>> ();
+
+    test<std::unordered_multimap<long, short>>();
+    test<std::unordered_multimap<short, double>>();
+}

Added: libcxx/trunk/test/std/containers/unord/unord.multiset/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.multiset/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.multiset/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.multiset/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <set>
+
+// template <class T, class Hash, class Compare, class Allocator, class Predicate>
+//   void erase_if(unordered_multiset<T, Hash, Compare, Allocator>& c, Predicate pred);
+
+#include <unordered_set>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+using Init = std::initializer_list<int>;
+
+template <typename M>
+M make (Init vals)
+{
+    M ret;
+    for (int v : vals)
+        ret.insert(v);
+    return ret;
+}
+
+template <typename M, typename Pred>
+void
+test0(Init vals, Pred p, Init expected)
+{
+    M s = make<M> (vals);
+    ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p)));
+    std::erase_if(s, p);
+    M e = make<M>(expected);
+    assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end())));
+}
+
+template <typename S>
+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, {});
+
+    test0<S>({1}, is1, {});
+    test0<S>({1}, is2, {1});
+
+    test0<S>({1,2}, is1, {2});
+    test0<S>({1,2}, is2, {1});
+    test0<S>({1,2}, is3, {1,2});
+    test0<S>({1,1}, is1, {});
+    test0<S>({1,1}, is3, {1,1});
+
+    test0<S>({1,2,3}, is1, {2,3});
+    test0<S>({1,2,3}, is2, {1,3});
+    test0<S>({1,2,3}, is3, {1,2});
+    test0<S>({1,2,3}, is4, {1,2,3});
+
+    test0<S>({1,1,1}, is1, {});
+    test0<S>({1,1,1}, is2, {1,1,1});
+    test0<S>({1,1,2}, is1, {2});
+    test0<S>({1,1,2}, is2, {1,1});
+    test0<S>({1,1,2}, is3, {1,1,2});
+    test0<S>({1,2,2}, is1, {2,2});
+    test0<S>({1,2,2}, is2, {1});
+    test0<S>({1,2,2}, is3, {1,2,2});
+    
+    test0<S>({1,2,3}, True,  {});
+    test0<S>({1,2,3}, False, {1,2,3});
+}
+
+int main()
+{
+    test<std::unordered_multiset<int>>();
+    test<std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, min_allocator<int>>> ();
+    test<std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, test_allocator<int>>> ();
+
+    test<std::unordered_multiset<long>>();
+    test<std::unordered_multiset<double>>();
+}

Added: libcxx/trunk/test/std/containers/unord/unord.set/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.set/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.set/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/containers/unord/unord.set/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <unordered_set>
+
+// template <class T, class Hash, class Compare, class Allocator, class Predicate>
+//   void erase_if(unorderd_set<T, Hash, Compare, Allocator>& c, Predicate pred);
+
+#include <unordered_set>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+using Init = std::initializer_list<int>;
+
+template <typename M>
+M make (Init vals)
+{
+    M ret;
+    for (int v : vals)
+        ret.insert(v);
+    return ret;
+}
+
+template <typename M, typename Pred>
+void
+test0(Init vals, Pred p, Init expected)
+{
+    M s = make<M> (vals);
+    ASSERT_SAME_TYPE(void, decltype(std::erase_if(s, p)));
+    std::erase_if(s, p);
+    M e = make<M>(expected);
+    assert((std::is_permutation(s.begin(), s.end(), e.begin(), e.end())));
+}
+
+
+template <typename S>
+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, {});
+
+    test0<S>({1}, is1, {});
+    test0<S>({1}, is2, {1});
+
+    test0<S>({1,2}, is1, {2});
+    test0<S>({1,2}, is2, {1});
+    test0<S>({1,2}, is3, {1,2});
+
+    test0<S>({1,2,3}, is1, {2,3});
+    test0<S>({1,2,3}, is2, {1,3});
+    test0<S>({1,2,3}, is3, {1,2});
+    test0<S>({1,2,3}, is4, {1,2,3});
+
+    test0<S>({1,2,3}, True,  {});
+    test0<S>({1,2,3}, False, {1,2,3});
+}
+
+int main()
+{
+    test<std::unordered_set<int>>();
+    test<std::unordered_set<int, std::hash<int>, std::equal_to<int>, min_allocator<int>>> ();
+    test<std::unordered_set<int, std::hash<int>, std::equal_to<int>, test_allocator<int>>> ();
+
+    test<std::unordered_set<long>>();
+    test<std::unordered_set<double>>();
+}

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <deque> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <forward_list> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <list> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <map> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <set> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <string> 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");

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <unordered_map> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <unordered_set> 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"

Modified: libcxx/trunk/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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 <vector> 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"

Added: libcxx/trunk/test/std/strings/strings.erasure/erase.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/strings.erasure/erase.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/strings/strings.erasure/erase.pass.cpp (added)
+++ libcxx/trunk/test/std/strings/strings.erasure/erase.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <string>
+
+// template <class charT, class traits, class Allocator, class U>
+//   void erase(basic_string<charT, traits, Allocator>& c, const U& value);
+  
+
+#include <string>
+#include <optional>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class U>
+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 <class S>
+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<typename S::value_type>;
+    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<std::string>();
+    test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>> ();
+    test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>> ();
+}

Added: libcxx/trunk/test/std/strings/strings.erasure/erase_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/strings.erasure/erase_if.pass.cpp?rev=349178&view=auto
==============================================================================
--- libcxx/trunk/test/std/strings/strings.erasure/erase_if.pass.cpp (added)
+++ libcxx/trunk/test/std/strings/strings.erasure/erase_if.pass.cpp Fri Dec 14 10:49:35 2018
@@ -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
+
+// <string>
+
+// template <class charT, class traits, class Allocator, class Predicate>
+//   void erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred);  
+
+#include <string>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+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 <typename S>
+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<std::string>();
+    test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>> ();
+    test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>> ();
+}

Modified: libcxx/trunk/www/cxx2a_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx2a_status.html?rev=349178&r1=349177&r2=349178&view=diff
==============================================================================
--- libcxx/trunk/www/cxx2a_status.html (original)
+++ libcxx/trunk/www/cxx2a_status.html Fri Dec 14 10:49:35 2018
@@ -131,7 +131,7 @@
 	<tr><td><a href="https://wg21.link/P1123R0">P1123R0</a></td><td>LWG</td><td>Editorial Guidance for merging P0019r8 and P0528r3</td><td>San Diego</td><td><i> </i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P1148R0">P1148R0</a></td><td>LWG</td><td>Cleaning up Clause 20</td><td>San Diego</td><td><i> </i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P1165R1">P1165R1</a></td><td>LWG</td><td>Make stateful allocator propagation more consistent for <tt>operator+(basic_string)</tt></td><td>San Diego</td><td><i> </i></td><td></td></tr>
-	<tr><td><a href="https://wg21.link/P1209R0">P1209R0</a></td><td>LWG</td><td>Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20</td><td>San Diego</td><td><i> </i></td><td></td></tr>
+	<tr><td><a href="https://wg21.link/P1209R0">P1209R0</a></td><td>LWG</td><td>Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20</td><td>San Diego</td><td>Complete</td><td>8.0</td></tr>
 	<tr><td><a href="https://wg21.link/P1210R0">P1210R0</a></td><td>LWG</td><td>Completing the Rebase of Library Fundamentals, Version 3, Working Draft</td><td>San Diego</td><td><i> </i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P1236R1">P1236R1</a></td><td>CWG</td><td>Alternative Wording for P0907R4 Signed Integers are Two's Complement</td><td>San Diego</td><td><i> </i></td><td></td></tr>
 	<tr><td><a href="https://wg21.link/P1248R1">P1248R1</a></td><td>LWG</td><td>Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)</td><td>San Diego</td><td><i> </i></td><td></td></tr>




More information about the libcxx-commits mailing list