[libcxx-commits] [libcxx] r358534 - Fix list/forward_list implementations of remove_if and unique to deal with predicates that are part of the sequence passed in. We already do this for remove.

Marshall Clow via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 16 15:11:26 PDT 2019


Author: marshall
Date: Tue Apr 16 15:11:26 2019
New Revision: 358534

URL: http://llvm.org/viewvc/llvm-project?rev=358534&view=rev
Log:
Fix list/forward_list implementations of remove_if and unique to deal with predicates that are part of the sequence passed in. We already do this for remove.

Modified:
    libcxx/trunk/include/forward_list
    libcxx/trunk/include/list
    libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp
    libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/unique_pred.pass.cpp
    libcxx/trunk/test/std/containers/sequences/list/list.ops/remove_if.pass.cpp
    libcxx/trunk/test/std/containers/sequences/list/list.ops/unique_pred.pass.cpp

Modified: libcxx/trunk/include/forward_list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/forward_list?rev=358534&r1=358533&r2=358534&view=diff
==============================================================================
--- libcxx/trunk/include/forward_list (original)
+++ libcxx/trunk/include/forward_list Tue Apr 16 15:11:26 2019
@@ -1505,7 +1505,7 @@ template <class _Tp, class _Alloc>
 void
 forward_list<_Tp, _Alloc>::remove(const value_type& __v)
 {
-    forward_list<_Tp, _Alloc> __deleted_nodes; // collect the nodes we're removing
+    forward_list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
     iterator __e = end();
     for (iterator __i = before_begin(); __i.__get_begin()->__next_ != nullptr;)
     {
@@ -1529,6 +1529,7 @@ template <class _Predicate>
 void
 forward_list<_Tp, _Alloc>::remove_if(_Predicate __pred)
 {
+    forward_list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
     iterator __e = end();
     for (iterator __i = before_begin(); __i.__get_begin()->__next_ != nullptr;)
     {
@@ -1537,7 +1538,7 @@ forward_list<_Tp, _Alloc>::remove_if(_Pr
             iterator __j = _VSTD::next(__i, 2);
             for (; __j != __e && __pred(*__j); ++__j)
                 ;
-            erase_after(__i, __j);
+            __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j);
             if (__j == __e)
                 break;
             __i = __j;
@@ -1552,13 +1553,14 @@ template <class _BinaryPredicate>
 void
 forward_list<_Tp, _Alloc>::unique(_BinaryPredicate __binary_pred)
 {
+    forward_list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
     for (iterator __i = begin(), __e = end(); __i != __e;)
     {
         iterator __j = _VSTD::next(__i);
         for (; __j != __e && __binary_pred(*__i, *__j); ++__j)
             ;
         if (__i.__get_begin()->__next_ != __j.__get_unsafe_node_pointer())
-            erase_after(__i, __j);
+            __deleted_nodes.splice_after(__deleted_nodes.before_begin(), *this, __i, __j);
         __i = __j;
     }
 }

Modified: libcxx/trunk/include/list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/list?rev=358534&r1=358533&r2=358534&view=diff
==============================================================================
--- libcxx/trunk/include/list (original)
+++ libcxx/trunk/include/list Tue Apr 16 15:11:26 2019
@@ -2167,6 +2167,7 @@ template <class _Pred>
 void
 list<_Tp, _Alloc>::remove_if(_Pred __pred)
 {
+    list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
     for (iterator __i = begin(), __e = end(); __i != __e;)
     {
         if (__pred(*__i))
@@ -2174,7 +2175,8 @@ list<_Tp, _Alloc>::remove_if(_Pred __pre
             iterator __j = _VSTD::next(__i);
             for (; __j != __e && __pred(*__j); ++__j)
                 ;
-            __i = erase(__i, __j);
+            __deleted_nodes.splice(__deleted_nodes.end(), *this, __i, __j);
+            __i = __j;
             if (__i != __e)
                 ++__i;
         }
@@ -2196,13 +2198,16 @@ template <class _BinaryPred>
 void
 list<_Tp, _Alloc>::unique(_BinaryPred __binary_pred)
 {
+    list<_Tp, _Alloc> __deleted_nodes(get_allocator()); // collect the nodes we're removing
     for (iterator __i = begin(), __e = end(); __i != __e;)
     {
         iterator __j = _VSTD::next(__i);
         for (; __j != __e && __binary_pred(*__i, *__j); ++__j)
             ;
-        if (++__i != __j)
-            __i = erase(__i, __j);
+        if (++__i != __j) {
+            __deleted_nodes.splice(__deleted_nodes.end(), *this, __i, __j);
+            __i = __j;
+            }
     }
 }
 

Modified: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp?rev=358534&r1=358533&r2=358534&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/remove_if.pass.cpp Tue Apr 16 15:11:26 2019
@@ -24,6 +24,15 @@ bool g(int i)
     return i < 3;
 }
 
+struct PredLWG529 {
+    PredLWG529 (int i) : i_(i) {};
+    ~PredLWG529() { i_ = -32767; }
+    bool operator() (const PredLWG529 &p) const { return p.i_ == i_; }
+
+    bool operator==(int i) const { return i == i_;}
+    int i_;
+};
+
 int main(int, char**)
 {
     {
@@ -88,6 +97,21 @@ int main(int, char**)
         assert(c1 == c2);
         assert(cp.count() == static_cast<std::size_t>(std::distance(std::begin(t1), std::end(t1))));
     }
+
+    { // LWG issue #526
+    int a1[] = {1, 2, 1, 3, 5, 8, 11};
+    int a2[] = {   2,    3, 5, 8, 11};
+    std::forward_list<PredLWG529> c(a1, a1 + 7);
+    c.remove_if(std::ref(c.front()));
+    for (size_t i = 0; i < 5; ++i)
+    {
+        assert(!c.empty());
+        assert(c.front() == a2[i]);
+        c.pop_front();
+    }
+    assert(c.empty());
+    }
+
 #if TEST_STD_VER >= 11
     {
         typedef int T;

Modified: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/unique_pred.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/unique_pred.pass.cpp?rev=358534&r1=358533&r2=358534&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/unique_pred.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.ops/unique_pred.pass.cpp Tue Apr 16 15:11:26 2019
@@ -16,6 +16,16 @@
 
 #include "min_allocator.h"
 
+struct PredLWG529 {
+    PredLWG529 (int i) : i_(i) {};
+    ~PredLWG529() { i_ = -32767; }
+    bool operator() (const PredLWG529 &lhs, const PredLWG529 &rhs) const { return lhs.i_ == rhs.i_; }
+
+    bool operator==(int i) const { return i == i_;}
+    int i_;
+};
+
+
 bool g(int x, int y)
 {
     return x == y;
@@ -71,6 +81,21 @@ int main(int, char**)
         c1.unique(g);
         assert(c1 == c2);
     }
+
+    { // LWG issue #526
+    int a1[] = {1, 1, 1, 2, 3, 5, 2, 11};
+    int a2[] = {1,       2, 3, 5, 2, 11};
+    std::forward_list<PredLWG529> c(a1, a1 + 8);
+    c.unique(std::ref(c.front()));
+    for (size_t i = 0; i < 6; ++i)
+    {
+        assert(!c.empty());
+        assert(c.front() == a2[i]);
+        c.pop_front();
+    }
+    assert(c.empty());
+    }
+
 #if TEST_STD_VER >= 11
     {
         typedef int T;

Modified: libcxx/trunk/test/std/containers/sequences/list/list.ops/remove_if.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/list/list.ops/remove_if.pass.cpp?rev=358534&r1=358533&r2=358534&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/list/list.ops/remove_if.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/list/list.ops/remove_if.pass.cpp Tue Apr 16 15:11:26 2019
@@ -27,6 +27,15 @@ bool g(int i)
     return i < 3;
 }
 
+struct PredLWG529 {
+    PredLWG529 (int i) : i_(i) {};
+    ~PredLWG529() { i_ = -32767; }
+    bool operator() (const PredLWG529 &p) const { return p.i_ == i_; }
+
+    bool operator==(int i) const { return i == i_;}
+    int i_;
+};
+
 typedef unary_counting_predicate<bool(*)(int), int> Predicate;
 
 int main(int, char**)
@@ -49,6 +58,19 @@ int main(int, char**)
     assert(c == std::list<int>(a2, a2+2));
     assert(cp.count() == 4);
     }
+    { // LWG issue #526
+    int a1[] = {1, 2, 1, 3, 5, 8, 11};
+    int a2[] = {2, 3, 5, 8, 11};
+    std::list<PredLWG529> c(a1, a1 + 7);
+    c.remove_if(std::ref(c.front()));
+    assert(c.size() == 5);
+    for (size_t i = 0; i < c.size(); ++i)
+    {
+        assert(c.front() == a2[i]);
+        c.pop_front();
+    }
+    }
+
 #if TEST_STD_VER >= 11
     {
     int a1[] = {1, 2, 3, 4};

Modified: libcxx/trunk/test/std/containers/sequences/list/list.ops/unique_pred.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/list/list.ops/unique_pred.pass.cpp?rev=358534&r1=358533&r2=358534&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/list/list.ops/unique_pred.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/list/list.ops/unique_pred.pass.cpp Tue Apr 16 15:11:26 2019
@@ -20,6 +20,15 @@ bool g(int x, int y)
     return x == y;
 }
 
+struct PredLWG529 {
+    PredLWG529 (int i) : i_(i) {};
+    ~PredLWG529() { i_ = -32767; }
+    bool operator() (const PredLWG529 &lhs, const PredLWG529 &rhs) const { return lhs.i_ == rhs.i_; }
+
+    bool operator==(int i) const { return i == i_;}
+    int i_;
+};
+
 int main(int, char**)
 {
     {
@@ -29,6 +38,20 @@ int main(int, char**)
     c.unique(g);
     assert(c == std::list<int>(a2, a2+4));
     }
+
+    { // LWG issue #526
+    int a1[] = {1, 1, 1, 2, 3, 5, 5, 2, 11};
+    int a2[] = {1,       2, 3, 5,    2, 11};
+    std::list<PredLWG529> c(a1, a1 + 9);
+    c.unique(std::ref(c.front()));
+    assert(c.size() == 6);
+    for (size_t i = 0; i < c.size(); ++i)
+    {
+        assert(c.front() == a2[i]);
+        c.pop_front();
+    }
+    }
+
 #if TEST_STD_VER >= 11
     {
     int a1[] = {2, 1, 1, 4, 4, 4, 4, 3, 3};




More information about the libcxx-commits mailing list