]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Make std::erase for linked lists convert to bool
authorJonathan Wakely <jwakely@redhat.com>
Thu, 6 Mar 2025 21:18:21 +0000 (21:18 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 31 Mar 2025 11:37:52 +0000 (12:37 +0100)
LWG 4135 (approved in Wrocław, November 2024) fixes the lambda
expressions used by std::erase for std::list and std::forward_list.
Previously they attempted to copy something that isn't required to be
copyable. Instead they should convert it to bool right away.

The issue resolution also changes the lambda's parameter to be const, so
that it can't modify the elements while comparing them.

libstdc++-v3/ChangeLog:

* include/std/forward_list (erase): Change lambda to have
explicit return type and const parameter type.
* include/std/list (erase): Likewise.
* testsuite/23_containers/forward_list/erasure.cc: Check lambda
is correct.
* testsuite/23_containers/list/erasure.cc: Likewise.

Reviewed-by: Patrick Palka <ppalka@redhat.com>
(cherry picked from commit e6e7b477bbdbfb3fee6b44087a59f94fd1e2c7a3)

libstdc++-v3/include/std/forward_list
libstdc++-v3/include/std/list
libstdc++-v3/testsuite/23_containers/forward_list/erasure.cc
libstdc++-v3/testsuite/23_containers/list/erasure.cc

index dfd7d48d1219a7146d76df2a86aeb2fa618a8f37..91dd6745bec43c9c0ee84405625eff97705ad5dc 100644 (file)
@@ -79,8 +79,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename forward_list<_Tp, _Alloc>::size_type
     erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value)
     {
-      using __elem_type = typename forward_list<_Tp, _Alloc>::value_type;
-      return std::erase_if(__cont, [&](__elem_type& __elem) {
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 4135. helper lambda of std::erase for list should specify return type
+      return std::erase_if(__cont, [&](const auto& __elem) -> bool {
          return __elem == __value;
       });
     }
index ff632fc1ab2f86837844939e30e2de0c12427fe6..d6126e493fa2bd87d4652a78c3e2286d1d3df44a 100644 (file)
@@ -103,8 +103,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename list<_Tp, _Alloc>::size_type
     erase(list<_Tp, _Alloc>& __cont, const _Up& __value)
     {
-      using __elem_type = typename list<_Tp, _Alloc>::value_type;
-      return std::erase_if(__cont, [&](__elem_type& __elem) {
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 4135. helper lambda of std::erase for list should specify return type
+      return std::erase_if(__cont, [&](const auto& __elem) -> bool {
          return __elem == __value;
       });
     }
index 271cb3a577e81266abc87713943f45a270a633ca..c5a7013f6b6bafa19df82d9762fdaa94130878fe 100644 (file)
@@ -53,6 +53,28 @@ test02()
   VERIFY( num == 0 );
 }
 
+// LWG 4135.
+// The helper lambda of std::erase for list should specify return type as bool
+void
+test_lwg4135()
+{
+  struct Bool {
+    Bool() = default;
+    Bool(const Bool&) = delete;
+    operator bool() const { return false; }
+  };
+
+  static Bool b;
+
+  struct Int {
+    Bool& operator==(Int) const { return b; }
+    void operator==(Int) = delete;
+  };
+
+  std::forward_list<Int> l;
+  std::erase(l, Int{});
+}
+
 int
 main()
 {
index c5d041526dcab4216373e2dc264b673f95a56d13..0df3a8772bdfddb4189c340cdce97a5b54ccb379 100644 (file)
@@ -52,6 +52,28 @@ test02()
   VERIFY( num == 0 );
 }
 
+// LWG 4135.
+// The helper lambda of std::erase for list should specify return type as bool
+void
+test_lwg4135()
+{
+  struct Bool {
+    Bool() = default;
+    Bool(const Bool&) = delete;
+    operator bool() const { return false; }
+  };
+
+  static Bool b;
+
+  struct Int {
+    Bool& operator==(Int) const { return b; }
+    void operator==(Int) = delete;
+  };
+
+  std::list<Int> l;
+  std::erase(l, Int{});
+}
+
 int
 main()
 {