On 11/26/18 6:18 AM, Jonathan Wakely wrote:
On 24/11/18 13:54 -0500, Ed Smith-Rowland wrote:
All,

I's very late but uniform container erasure is, I think, the last little tidbit to graduate from fundamentals/v2 to std at the last meeting.  I think it would be a shame not to nudge this into gcc-9.  The routines are very short so I just copied them. Ditto the testcases (with adjustments).  The node erasure tool was moved from experimental to std/bits and adjustments made to affected *set/*map headers.

The experimental code has been in our tree since 2015.

This builds and tests clean on x86_64-linux.

OK for trunk as it only touches experimental C++2a and TS material.
Thanks.

I pointed out to the committee that the erase_if functions added to
C++20 completely overlook P0646R1 "Improving the Return Value of
Erase-Like Algorithms" and so fail to preserve the useful information
returned by the members of the linked list containers.

I expect that to get fixed as a defect. If you have time and
motivation, I think we should make that change proactively in
libstdc++. The Library Fundamentals versions can continue to return
void, but the ones in namespace std can return the number of elements
removed.

I committed essentially what I started with (attached) as a baseline.

I would like to change the return as you suggest in another patch.

It seems to me that the intent of UCE is to have the same API for all containers.

So all erase_if would have size_type returns, including vector, string, deque.  Not a problem as those are const time.

It looks like the node erasure tool needs to maintain a count of erased nodes.  (it can't use erase(KeyT k) that returns a count since it involves a predicate rather than key compare.  Too bad there aren't 'size_t erase_if(Pred)' members.)  No biggie - the complexity isn't changed by keeping count.

Holy crap.  i just noticed that *set/*map don't have plain erase() only erase_if()!

I need to implement final: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1209r0.html before I do anything.  Both for experimental and std.

Ed



2018-11-28  Edward Smith-Rowland  <3dw...@verizon.net>

        Implement uniform container erasure for C++20.
        * include/Makefile.am: Move erase_if.h.
        * include/Makefile.in: Move erase_if.h.
        * include/experimental/bits/erase_if.h: Move ...
        * include/bits/erase_if.h: ... here.
        * include/experimental/map: Move erase_if.h.
        * include/experimental/set: Move erase_if.h.
        * include/experimental/unordered_map: Move erase_if.h.
        * include/experimental/unordered_set: Move erase_if.h.
        * include/std/deque (erase_if, erase): New functions.
        * include/std/forward_list: Ditto.
        * include/std/list: Ditto.
        * include/std/map: Ditto.
        * include/std/set: Ditto.
        * include/std/string: Ditto.
        * include/std/unordered_map: Ditto.
        * include/std/unordered_set: Ditto.
        * include/std/vector: Ditto.
        * testsuite/21_strings/basic_string/erasure.cc: New test.
        * testsuite/23_containers/deque/erasure.cc: New test.
        * testsuite/23_containers/forward_list/erasure.cc: New test.
        * testsuite/23_containers/list/erasure.cc: New test.
        * testsuite/23_containers/map/erasure.cc: New test.
        * testsuite/23_containers/set/erasure.cc: New test.
        * testsuite/23_containers/unordered_map/erasure.cc: New test.
        * testsuite/23_containers/unordered_set/erasure.cc: New test.
        * testsuite/23_containers/vector/erasure.cc: New test.

Index: include/Makefile.am
===================================================================
--- include/Makefile.am (revision 266566)
+++ include/Makefile.am (working copy)
@@ -106,6 +106,7 @@
        ${bits_srcdir}/cpp_type_traits.h \
        ${bits_srcdir}/deque.tcc \
        ${bits_srcdir}/enable_special_members.h \
+       ${bits_srcdir}/erase_if.h \
        ${bits_srcdir}/forward_list.h \
        ${bits_srcdir}/forward_list.tcc \
        ${bits_srcdir}/fs_dir.h \
@@ -710,7 +711,6 @@
 experimental_bits_srcdir = ${glibcxx_srcdir}/include/experimental/bits
 experimental_bits_builddir = ./experimental/bits
 experimental_bits_headers = \
-       ${experimental_bits_srcdir}/erase_if.h \
        ${experimental_bits_srcdir}/lfts_config.h \
        ${experimental_bits_srcdir}/net.h \
        ${experimental_bits_srcdir}/shared_ptr.h \
Index: include/Makefile.in
===================================================================
--- include/Makefile.in (revision 266566)
+++ include/Makefile.in (working copy)
@@ -449,6 +449,7 @@
        ${bits_srcdir}/cpp_type_traits.h \
        ${bits_srcdir}/deque.tcc \
        ${bits_srcdir}/enable_special_members.h \
+       ${bits_srcdir}/erase_if.h \
        ${bits_srcdir}/forward_list.h \
        ${bits_srcdir}/forward_list.tcc \
        ${bits_srcdir}/fs_dir.h \
@@ -1052,7 +1053,6 @@
 experimental_bits_srcdir = ${glibcxx_srcdir}/include/experimental/bits
 experimental_bits_builddir = ./experimental/bits
 experimental_bits_headers = \
-       ${experimental_bits_srcdir}/erase_if.h \
        ${experimental_bits_srcdir}/lfts_config.h \
        ${experimental_bits_srcdir}/net.h \
        ${experimental_bits_srcdir}/shared_ptr.h \
Index: include/bits/erase_if.h
===================================================================
--- include/bits/erase_if.h     (revision 266566)
+++ include/bits/erase_if.h     (working copy)
@@ -1,4 +1,4 @@
-// <experimental/bits/erase_if.h> -*- C++ -*-
+// <bits/erase_if.h> -*- C++ -*-
 
 // Copyright (C) 2015-2018 Free Software Foundation, Inc.
 //
@@ -22,27 +22,22 @@
 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 // <http://www.gnu.org/licenses/>.
 
-/** @file experimental/bits/erase_if.h
+/** @file bits/erase_if.h
  *  This is an internal header file, included by other library headers.
  *  Do not attempt to use it directly.
  */
 
-#ifndef _GLIBCXX_EXPERIMENTAL_ERASE_IF_H
-#define _GLIBCXX_EXPERIMENTAL_ERASE_IF_H 1
+#ifndef _GLIBCXX_ERASE_IF_H
+#define _GLIBCXX_ERASE_IF_H 1
 
 #pragma GCC system_header
 
 #if __cplusplus >= 201402L
-#include <experimental/bits/lfts_config.h>
 
 namespace std
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-namespace experimental
-{
-inline namespace fundamentals_v2
-{
   namespace __detail
   {
     template<typename _Container, typename _Predicate>
@@ -59,8 +54,6 @@
        }
       }
   } // namespace __detail
-} // inline namespace fundamentals_v2
-} // namespace experimental
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
@@ -67,4 +60,4 @@
 
 #endif // C++14
 
-#endif // _GLIBCXX_EXPERIMENTAL_ERASE_IF_H
+#endif // _GLIBCXX_ERASE_IF_H
Index: include/experimental/bits/erase_if.h
===================================================================
--- include/experimental/bits/erase_if.h        (revision 266566)
+++ include/experimental/bits/erase_if.h        (nonexistent)
@@ -1,70 +0,0 @@
-// <experimental/bits/erase_if.h> -*- C++ -*-
-
-// Copyright (C) 2015-2018 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-/** @file experimental/bits/erase_if.h
- *  This is an internal header file, included by other library headers.
- *  Do not attempt to use it directly.
- */
-
-#ifndef _GLIBCXX_EXPERIMENTAL_ERASE_IF_H
-#define _GLIBCXX_EXPERIMENTAL_ERASE_IF_H 1
-
-#pragma GCC system_header
-
-#if __cplusplus >= 201402L
-#include <experimental/bits/lfts_config.h>
-
-namespace std
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-namespace experimental
-{
-inline namespace fundamentals_v2
-{
-  namespace __detail
-  {
-    template<typename _Container, typename _Predicate>
-      void
-      __erase_nodes_if(_Container& __cont, _Predicate __pred)
-      {
-       for (auto __iter = __cont.begin(), __last = __cont.end();
-            __iter != __last;)
-       {
-         if (__pred(*__iter))
-           __iter = __cont.erase(__iter);
-         else
-           ++__iter;
-       }
-      }
-  } // namespace __detail
-} // inline namespace fundamentals_v2
-} // namespace experimental
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace std
-
-#endif // C++14
-
-#endif // _GLIBCXX_EXPERIMENTAL_ERASE_IF_H
Index: include/experimental/map
===================================================================
--- include/experimental/map    (revision 266566)
+++ include/experimental/map    (working copy)
@@ -34,7 +34,7 @@
 #if __cplusplus >= 201402L
 
 #include <map>
-#include <experimental/bits/erase_if.h>
+#include <bits/erase_if.h>
 #include <experimental/memory_resource>
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -49,13 +49,13 @@
           typename _Predicate>
     inline void
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
           typename _Predicate>
     inline void
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   namespace pmr {
     template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
Index: include/experimental/set
===================================================================
--- include/experimental/set    (revision 266566)
+++ include/experimental/set    (working copy)
@@ -34,7 +34,7 @@
 #if __cplusplus >= 201402L
 
 #include <set>
-#include <experimental/bits/erase_if.h>
+#include <bits/erase_if.h>
 #include <experimental/memory_resource>
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -49,13 +49,13 @@
           typename _Predicate>
     inline void
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   template<typename _Key, typename _Compare, typename _Alloc,
           typename _Predicate>
     inline void
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   namespace pmr {
     template<typename _Key, typename _Compare = less<_Key>>
Index: include/experimental/unordered_map
===================================================================
--- include/experimental/unordered_map  (revision 266566)
+++ include/experimental/unordered_map  (working copy)
@@ -34,7 +34,7 @@
 #if __cplusplus >= 201402L
 
 #include <unordered_map>
-#include <experimental/bits/erase_if.h>
+#include <bits/erase_if.h>
 #include <experimental/memory_resource>
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -50,7 +50,7 @@
     inline void
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
           typename _Alloc, typename _Predicate>
@@ -57,7 +57,7 @@
     inline void
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   namespace pmr {
     template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
Index: include/experimental/unordered_set
===================================================================
--- include/experimental/unordered_set  (revision 266566)
+++ include/experimental/unordered_set  (working copy)
@@ -34,7 +34,7 @@
 #if __cplusplus >= 201402L
 
 #include <unordered_set>
-#include <experimental/bits/erase_if.h>
+#include <bits/erase_if.h>
 #include <experimental/memory_resource>
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -50,7 +50,7 @@
     inline void
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
           typename _Predicate>
@@ -57,7 +57,7 @@
     inline void
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
-    { __detail::__erase_nodes_if(__cont, __pred); }
+    { std::__detail::__erase_nodes_if(__cont, __pred); }
 
   namespace pmr {
     template<typename _Key, typename _Hash = hash<_Key>,
Index: include/std/deque
===================================================================
--- include/std/deque   (revision 266566)
+++ include/std/deque   (working copy)
@@ -87,4 +87,27 @@
 } // namespace std
 #endif // C++17
 
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Tp, typename _Alloc, typename _Predicate>
+    void
+    erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
+    {
+      __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
+                  __cont.end());
+    }
+
+  template<typename _Tp, typename _Alloc, typename _Up>
+    void
+    erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
+    {
+      __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
+                  __cont.end());
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif /* _GLIBCXX_DEQUE */
Index: include/std/forward_list
===================================================================
--- include/std/forward_list    (revision 266566)
+++ include/std/forward_list    (working copy)
@@ -60,6 +60,27 @@
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++17
+
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Tp, typename _Alloc, typename _Predicate>
+    inline void 
+    erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred)
+    { __cont.remove_if(__pred); }
+
+  template<typename _Tp, typename _Alloc, typename _Up>
+    inline void
+    erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value)
+    {
+      using __elem_type = typename forward_list<_Tp, _Alloc>::value_type;
+      erase_if(__cont, [&](__elem_type& __elem) { return __elem == __value; });
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif // C++11
 
 #endif // _GLIBCXX_FORWARD_LIST
Index: include/std/list
===================================================================
--- include/std/list    (revision 266566)
+++ include/std/list    (working copy)
@@ -84,4 +84,25 @@
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++17
+
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Tp, typename _Alloc, typename _Predicate>
+    inline void
+    erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred)
+    { __cont.remove_if(__pred); }
+
+  template<typename _Tp, typename _Alloc, typename _Up>
+    inline void
+    erase(list<_Tp, _Alloc>& __cont, const _Up& __value)
+    {
+      using __elem_type = typename list<_Tp, _Alloc>::value_type;
+      erase_if(__cont, [&](__elem_type& __elem) { return __elem == __value; });
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif /* _GLIBCXX_LIST */
Index: include/std/map
===================================================================
--- include/std/map     (revision 266566)
+++ include/std/map     (working copy)
@@ -61,6 +61,7 @@
 #include <bits/stl_map.h>
 #include <bits/stl_multimap.h>
 #include <bits/range_access.h>
+#include <bits/erase_if.h>
 
 #ifdef _GLIBCXX_DEBUG
 # include <debug/map>
@@ -90,4 +91,23 @@
 } // namespace std
 #endif // C++17
 
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
+          typename _Predicate>
+    inline void
+    erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
+    { __detail::__erase_nodes_if(__cont, __pred); }
+
+  template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
+          typename _Predicate>
+    inline void
+    erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
+    { __detail::__erase_nodes_if(__cont, __pred); }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif /* _GLIBCXX_MAP */
Index: include/std/set
===================================================================
--- include/std/set     (revision 266566)
+++ include/std/set     (working copy)
@@ -61,6 +61,7 @@
 #include <bits/stl_set.h>
 #include <bits/stl_multiset.h>
 #include <bits/range_access.h>
+#include <bits/erase_if.h>
 
 #ifdef _GLIBCXX_DEBUG
 # include <debug/set>
@@ -86,4 +87,23 @@
 } // namespace std
 #endif // C++17
 
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Key, typename _Compare, typename _Alloc,
+          typename _Predicate>
+    inline void
+    erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
+    { __detail::__erase_nodes_if(__cont, __pred); }
+
+  template<typename _Key, typename _Compare, typename _Alloc,
+          typename _Predicate>
+    inline void
+    erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
+    { __detail::__erase_nodes_if(__cont, __pred); }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif /* _GLIBCXX_SET */
Index: include/std/string
===================================================================
--- include/std/string  (revision 266566)
+++ include/std/string  (working copy)
@@ -51,6 +51,7 @@
 #include <bits/range_access.h>
 #include <bits/basic_string.h>
 #include <bits/basic_string.tcc>
+#include <algorithm> // For remove and remove_if
 
 #if __cplusplus >= 201703L && _GLIBCXX_USE_CXX11_ABI
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -72,4 +73,28 @@
 } // namespace std
 #endif // C++17
 
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _CharT, typename _Traits, typename _Alloc,
+          typename _Predicate>
+    inline void
+    erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
+    {
+      __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
+                  __cont.end());
+    }
+
+  template<typename _CharT, typename _Traits, typename _Alloc, typename _Up>
+    inline void
+    erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
+    {
+      __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
+                  __cont.end());
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif /* _GLIBCXX_STRING */
Index: include/std/unordered_map
===================================================================
--- include/std/unordered_map   (revision 266566)
+++ include/std/unordered_map   (working copy)
@@ -46,6 +46,7 @@
 #include <bits/hashtable.h>
 #include <bits/unordered_map.h>
 #include <bits/range_access.h>
+#include <bits/erase_if.h>
 
 #ifdef _GLIBCXX_DEBUG
 # include <debug/unordered_map>
@@ -76,6 +77,28 @@
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++17
+
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
+          typename _Alloc, typename _Predicate>
+    inline void
+    erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
+            _Predicate __pred)
+    { __detail::__erase_nodes_if(__cont, __pred); }
+
+  template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
+          typename _Alloc, typename _Predicate>
+    inline void
+    erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
+            _Predicate __pred)
+    { __detail::__erase_nodes_if(__cont, __pred); }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif // C++11
 
 #endif // _GLIBCXX_UNORDERED_MAP
Index: include/std/unordered_set
===================================================================
--- include/std/unordered_set   (revision 266566)
+++ include/std/unordered_set   (working copy)
@@ -46,6 +46,7 @@
 #include <bits/hashtable.h>
 #include <bits/unordered_set.h>
 #include <bits/range_access.h>
+#include <bits/erase_if.h>
 
 #ifdef _GLIBCXX_DEBUG
 # include <debug/unordered_set>
@@ -76,6 +77,15 @@
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++17
+
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif // C++11
 
 #endif // _GLIBCXX_UNORDERED_SET
Index: include/std/vector
===================================================================
--- include/std/vector  (revision 266566)
+++ include/std/vector  (working copy)
@@ -90,4 +90,27 @@
 } // namespace std
 #endif // C++17
 
+#if __cplusplus > 201703L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Tp, typename _Alloc, typename _Predicate>
+    inline void
+    erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
+    {
+      __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
+                  __cont.end());
+    }
+
+  template<typename _Tp, typename _Alloc, typename _Up>
+    inline void
+    erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
+    {
+      __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
+                  __cont.end());
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+
 #endif /* _GLIBCXX_VECTOR */
Index: testsuite/21_strings/basic_string/erasure.cc
===================================================================
--- testsuite/21_strings/basic_string/erasure.cc        (nonexistent)
+++ testsuite/21_strings/basic_string/erasure.cc        (working copy)
@@ -0,0 +1,53 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto is_vowel = [](const char c)
+  {
+    return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
+  };
+
+  std::string str("cute fluffy kittens");
+  std::erase_if(str, is_vowel);
+  VERIFY( str == "ct flffy kttns" );
+}
+
+void
+test02()
+{
+  std::string str = "cute fluffy kittens";
+  std::erase(str, 'f');
+  VERIFY( str == "cute luy kittens" );
+  std::erase(str, 'z');
+  VERIFY( str == "cute luy kittens" );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/deque/erasure.cc
===================================================================
--- testsuite/23_containers/deque/erasure.cc    (nonexistent)
+++ testsuite/23_containers/deque/erasure.cc    (working copy)
@@ -0,0 +1,52 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <deque>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto is_odd = [](const int i) { return i % 2 != 0; };
+
+  std::deque<int> d{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase_if(d, is_odd);
+  std::deque<int> t{ 10, 12, 14, 18 };
+  VERIFY( d == t );
+}
+
+void
+test02()
+{
+  std::deque<int> d{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase(d, 14);
+  std::deque<int> t{ 10, 11, 12, 15, 17, 18, 19 };
+  VERIFY( d == t );
+  std::erase(d, 20);
+  VERIFY( d == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/forward_list/erasure.cc
===================================================================
--- testsuite/23_containers/forward_list/erasure.cc     (nonexistent)
+++ testsuite/23_containers/forward_list/erasure.cc     (working copy)
@@ -0,0 +1,52 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <forward_list>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto is_odd = [](const int i) { return i % 2 != 0; };
+
+  std::forward_list<int> fl{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase_if(fl, is_odd);
+  std::forward_list<int> t{ 10, 12, 14, 18 };
+  VERIFY( fl == t );
+}
+
+void
+test02()
+{
+  std::forward_list<int> fl{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase(fl, 14);
+  std::forward_list<int> t{ 10, 11, 12, 15, 17, 18, 19 };
+  VERIFY( fl == t );
+  std::erase(fl, 20);
+  VERIFY( fl == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/list/erasure.cc
===================================================================
--- testsuite/23_containers/list/erasure.cc     (nonexistent)
+++ testsuite/23_containers/list/erasure.cc     (working copy)
@@ -0,0 +1,52 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <list>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto is_odd = [](const int i) { return i % 2 != 0; };
+
+  std::list<int> l{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase_if(l, is_odd);
+  std::list<int> t{ 10, 12, 14, 18 };
+  VERIFY( l == t );
+}
+
+void
+test02()
+{
+  std::list<int> l{ 0, 11, 0, 0, 22, 33, 0, 0, 44, 0 };
+  std::erase(l, 0);
+  std::list<int> t{ 11, 22, 33, 44 };
+  VERIFY( l == t );
+  std::erase(l, 55);
+  VERIFY( l == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/map/erasure.cc
===================================================================
--- testsuite/23_containers/map/erasure.cc      (nonexistent)
+++ testsuite/23_containers/map/erasure.cc      (working copy)
@@ -0,0 +1,61 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <map>
+#include <testsuite_hooks.h>
+
+auto is_odd_pair = [](const std::pair<const int, std::string>& p)
+{
+  return p.first % 2 != 0;
+};
+
+void
+test01()
+{
+  std::map<int, std::string> m{ { 10, "A" }, { 11, "B" },
+                               { 12, "C" }, { 14, "D" },
+                               { 15, "E" }, { 17, "F" },
+                               { 18, "G" }, { 19, "H" } };
+  std::erase_if(m, is_odd_pair);
+  std::map<int, std::string> t{ { 10, "A" }, { 12, "C" },
+                               { 14, "D" }, { 18, "G" } };
+  VERIFY( m == t );
+}
+
+void
+test02()
+{
+  std::multimap<int, std::string> mm{ { 20, "S" }, { 21, "T" },
+                                     { 22, "U" }, { 22, "V" },
+                                     { 23, "W" }, { 23, "X" },
+                                     { 24, "Y" }, { 25, "Z" } };
+  std::erase_if(mm, is_odd_pair);
+  std::multimap<int, std::string> t{ { 20, "S" }, { 22, "U" },
+                                    { 22, "V" }, { 24, "Y" } };
+  VERIFY( mm == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/set/erasure.cc
===================================================================
--- testsuite/23_containers/set/erasure.cc      (nonexistent)
+++ testsuite/23_containers/set/erasure.cc      (working copy)
@@ -0,0 +1,50 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <set>
+#include <testsuite_hooks.h>
+
+auto is_odd = [](const int i) { return i % 2 != 0; };
+
+void
+test01()
+{
+  std::set<int> s{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase_if(s, is_odd);
+  std::set<int> t{ 10, 12, 14, 18 };
+  VERIFY( s == t );
+}
+
+void
+test02()
+{
+  std::multiset<int> ms{ 20, 21, 22, 22, 23, 23, 24, 25 };
+  std::erase_if(ms, is_odd);
+  std::multiset<int> t{ 20, 22, 22, 24 };
+  VERIFY( ms == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/unordered_map/erasure.cc
===================================================================
--- testsuite/23_containers/unordered_map/erasure.cc    (nonexistent)
+++ testsuite/23_containers/unordered_map/erasure.cc    (working copy)
@@ -0,0 +1,61 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <unordered_map>
+#include <testsuite_hooks.h>
+
+auto is_odd_pair = [](const std::pair<const int, std::string>& p)
+{
+  return p.first % 2 != 0;
+};
+
+void
+test01()
+{
+  std::unordered_map<int, std::string> um{ { 10, "A" }, { 11, "B" },
+                                          { 12, "C" }, { 14, "D" },
+                                          { 15, "E" }, { 17, "F" },
+                                          { 18, "G" }, { 19, "H" } };
+  std::erase_if(um, is_odd_pair);
+  std::unordered_map<int, std::string> t{ { 10, "A" }, { 12, "C" },
+                                         { 14, "D" }, { 18, "G" } };
+  VERIFY( um == t );
+}
+
+void
+test02()
+{
+  std::unordered_multimap<int, std::string> umm{ { 20, "S" }, { 21, "T" },
+                                                { 22, "U" }, { 22, "V" },
+                                                { 23, "W" }, { 23, "X" },
+                                                { 24, "Y" }, { 25, "Z" } };
+  std::erase_if(umm, is_odd_pair);
+  std::unordered_multimap<int, std::string> t{ { 20, "S" }, { 22, "U" },
+                                              { 22, "V" }, { 24, "Y" } };
+  VERIFY( umm == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/unordered_set/erasure.cc
===================================================================
--- testsuite/23_containers/unordered_set/erasure.cc    (nonexistent)
+++ testsuite/23_containers/unordered_set/erasure.cc    (working copy)
@@ -0,0 +1,52 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <unordered_set>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto is_odd = [](const int i) { return i % 2 != 0; };
+
+  std::unordered_set<int> us{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase_if(us, is_odd);
+  std::unordered_set<int> t{ 10, 12, 14, 18 };
+  VERIFY( us == t );
+}
+
+void
+test02()
+{
+  auto is_odd = [](const int i) { return i % 2 != 0; };
+
+  std::unordered_multiset<int> ums{ 20, 21, 22, 22, 23, 23, 24, 25 };
+  std::erase_if(ums, is_odd);
+  std::unordered_multiset<int> t{ 20, 22, 22, 24 };
+  VERIFY( ums == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}
Index: testsuite/23_containers/vector/erasure.cc
===================================================================
--- testsuite/23_containers/vector/erasure.cc   (nonexistent)
+++ testsuite/23_containers/vector/erasure.cc   (working copy)
@@ -0,0 +1,52 @@
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  auto is_odd = [](const int i) { return i % 2 != 0; };
+
+  std::vector<int> v{ 10, 11, 12, 14, 15, 17, 18, 19 };
+  std::erase_if(v, is_odd);
+  std::vector<int> t{ 10, 12, 14, 18 };
+  VERIFY( v == t );
+}
+
+void
+test02()
+{
+  std::vector<int> v{ 0, 11, 0, 0, 22, 33, 0, 0, 44, 0 };
+  std::erase(v, 0);
+  std::vector<int> t{ 11, 22, 33, 44 };
+  VERIFY( v == t );
+  std::erase(v, 55);
+  VERIFY( v == t );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+
+  return 0;
+}

Reply via email to