]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Call predicate with non-const values in std::erase_if [PR107850]
authorJonathan Wakely <jwakely@redhat.com>
Thu, 24 Nov 2022 21:09:03 +0000 (21:09 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 25 Nov 2022 15:06:25 +0000 (15:06 +0000)
As specified in the standard, the predicate for std::erase_if has to be
invocable as non-const with a non-const lvalues argument. Restore
support for predicates that only accept non-const arguments.

It's not strictly nevessary to change it for the set and unordered_set
overloads, because they only give const access to the elements anyway.
I've done it for them too just to keep them all consistent.

libstdc++-v3/ChangeLog:

PR libstdc++/107850
* include/bits/erase_if.h (__erase_nodes_if): Use non-const
reference to the container.
* include/experimental/map (erase_if): Likewise.
* include/experimental/set (erase_if): Likewise.
* include/experimental/unordered_map (erase_if): Likewise.
* include/experimental/unordered_set (erase_if): Likewise.
* include/std/map (erase_if): Likewise.
* include/std/set (erase_if): Likewise.
* include/std/unordered_map (erase_if): Likewise.
* include/std/unordered_set (erase_if): Likewise.
* testsuite/23_containers/map/erasure.cc: Check with
const-incorrect predicate.
* testsuite/23_containers/set/erasure.cc: Likewise.
* testsuite/23_containers/unordered_map/erasure.cc: Likewise.
* testsuite/23_containers/unordered_set/erasure.cc: Likewise.
* testsuite/experimental/map/erasure.cc: Likewise.
* testsuite/experimental/set/erasure.cc: Likewise.
* testsuite/experimental/unordered_map/erasure.cc: Likewise.
* testsuite/experimental/unordered_set/erasure.cc: Likewise.

17 files changed:
libstdc++-v3/include/bits/erase_if.h
libstdc++-v3/include/experimental/map
libstdc++-v3/include/experimental/set
libstdc++-v3/include/experimental/unordered_map
libstdc++-v3/include/experimental/unordered_set
libstdc++-v3/include/std/map
libstdc++-v3/include/std/set
libstdc++-v3/include/std/unordered_map
libstdc++-v3/include/std/unordered_set
libstdc++-v3/testsuite/23_containers/map/erasure.cc
libstdc++-v3/testsuite/23_containers/set/erasure.cc
libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc
libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc
libstdc++-v3/testsuite/experimental/map/erasure.cc
libstdc++-v3/testsuite/experimental/set/erasure.cc
libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc
libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc

index 397207f4b56804e12c9a384bae48787cedb9826e..b336e263d2d1d7b8b4b44e41692c83d9ae232399 100644 (file)
@@ -49,7 +49,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     template<typename _Container, typename _UnsafeContainer,
             typename _Predicate>
       typename _Container::size_type
-      __erase_nodes_if(_Container& __cont, const _UnsafeContainer& __ucont,
+      __erase_nodes_if(_Container& __cont, _UnsafeContainer& __ucont,
                       _Predicate __pred)
       {
        typename _Container::size_type __num = 0;
index 525252b83c1ca5d0dcb28bdc73b217f57befc283..9557a2aec1c550dc64c0c73a167f1f0c72495ba5 100644 (file)
@@ -53,8 +53,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>&
-       __ucont = __cont;
+      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -63,8 +62,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>&
-       __ucont = __cont;
+      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
index b42a3cdcf1ad51d2c871baf4bb74bc1d74427134..7d142e081d99ca1353882c2b0a6aeaf20c826d10 100644 (file)
@@ -53,7 +53,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -62,7 +62,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
index ce56c2afb8c4f3748385040601c2870ad03d28f7..02bba7edab923bc5d0487281ed5624769d1702e3 100644 (file)
@@ -54,7 +54,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -65,7 +65,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
index c7075874daf6f99c4fb201b47ce105986c40ea5c..04bbb7fb700cb815f1ea2a69d54690278a761d27 100644 (file)
@@ -54,7 +54,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -65,7 +65,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
index c973a8e6eca071c9c2df94b3bcd25d4460615f11..9bf484dc5e3fadbdd0b3f1e6e87c0ec817566ddb 100644 (file)
@@ -98,8 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>&
-       __ucont = __cont;
+      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -108,8 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>&
-       __ucont = __cont;
+      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 _GLIBCXX_END_NAMESPACE_VERSION
index 4cbcba1dc2ffc0a1568c342b75e5b4934a7a7836..3ada45c91544745d24d15f3da5140e427149cd42 100644 (file)
@@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename set<_Key, _Compare, _Alloc>::size_type
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -103,7 +103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename multiset<_Key, _Compare, _Alloc>::size_type
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 _GLIBCXX_END_NAMESPACE_VERSION
index 323edcd722da4591136a262d7025adfccfc6d38d..38c4987c795788533e12c65554f57044c5ba9dad 100644 (file)
@@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -90,7 +90,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
index 998417f5d14f959c1aa4f30edbd1670cef8284f6..09f74ab6b2cae0f70a6acbb3fa10a38b7232694a 100644 (file)
@@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -89,7 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
             _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
        __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
index badf7896df6a675888119087522f1be0f78c10b3..643ad0a3f17fd8f84d6b1ad68619857e92e15e0b 100644 (file)
@@ -61,11 +61,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::map<int, int> m;
+  std::erase_if(m, pred);
+  std::multimap<int, int> mm;
+  std::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index fe0c4b8766b5180e2b61dd5604d754ce6865d2af..bfa28f2600966e6b09bbc65789e9b0172f685562 100644 (file)
@@ -49,11 +49,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::set<int> s;
+  std::erase_if(s, pred);
+  std::multiset<int> ms;
+  std::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index e6018186bf28a7bcb2b4d390c9a4a27d10315e5b..8392e538ac7509e53da7afa36a0975c99a663c8b 100644 (file)
@@ -61,11 +61,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_map<int, int> m;
+  std::erase_if(m, pred);
+  std::unordered_multimap<int, int> mm;
+  std::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index 4cb80413ff0f7acaaa0441d417c228beb5306d63..768454942893d38e6ff8611b7ba7470f1501d694 100644 (file)
@@ -51,11 +51,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_set<int> s;
+  std::erase_if(s, pred);
+  std::unordered_multiset<int> ms;
+  std::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index 8470ab2e99b4da47eae239338bf177f22da30c72..b377926898f9fe21b85d2dd9f53771e9aa26440a 100644 (file)
@@ -52,11 +52,24 @@ test02()
   VERIFY( mm == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::map<int, int> m;
+  std::experimental::erase_if(m, pred);
+  std::multimap<int, int> mm;
+  std::experimental::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index 1e04c3461a4c5a40ecd97d464199cc416c7f4a58..b4272282c320c8ecb365d348ee9fd89f7fdc225a 100644 (file)
@@ -40,11 +40,24 @@ test02()
   VERIFY( ms == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::set<int> s;
+  std::experimental::erase_if(s, pred);
+  std::multiset<int> ms;
+  std::experimental::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index 022f57583b03a47003d7493c83576ac3918bfd52..cd281bc70dad8bc90815c23f18ad611e025f909b 100644 (file)
@@ -52,11 +52,24 @@ test02()
   VERIFY( umm == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_map<int, int> m;
+  std::experimental::erase_if(m, pred);
+  std::unordered_multimap<int, int> mm;
+  std::experimental::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
index d261812d4ec43d0b8dda7d6113d58ca947584657..918f455f5c001658cd6f91d738071b2d6db4b9e3 100644 (file)
@@ -42,11 +42,24 @@ test02()
   VERIFY( ums == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_set<int> s;
+  std::experimental::erase_if(s, pred);
+  std::unordered_multiset<int> ms;
+  std::experimental::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }