Thread: remove_if

  1. #1
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463

    remove_if

    I'm looking at the example for the function object predicate. Here is the example that show what you should not do with the predicate
    Code:
    #include <iostream>
    #include <list>
    #include <algorithm>
    #include <iterator>
    using namespace std;
    
    class Nth
    {
    private:
      int nth;
      int count;
    public:
      Nth ( int n) : nth(n) , count(0) {}
      bool operator() (int) // need in input, empty input field yield errors
      {
         return ++count == nth;
      }
    };
    
    int main()
    {
        list<int> coll;
        // insert elements from 1 to 9
        for ( int i = 0 ; i <= 9 ; ++i)
        {
            coll.push_back(i);
        }
    
        copy(coll.begin(),coll.end(),
                          ostream_iterator<int>(cout," ") );
        cout << endl;
    
        list<int>::iterator pos;
        pos = remove_if(coll.begin(),coll.end(),Nth(3));
    
        coll.erase(pos,coll.end());
        copy(coll.begin(),coll.end(),
                           ostream_iterator<int>(cout," ") );
    	pos = find_if(coll.begin() , coll.end() , Nth(3));
    	cout << endl;
        cout << *pos << endl;
    
        cout << endl;
    }
    Code:
    // output
    1 2 3 4 5 6 7 8 9 10
    1 2 4 5 7 8 9 10

    The author didn't explain it perfectly clear how that function fails. He only mentioned the use of find_if in the template of remove_if. But that wouldn't have cause the problem, would it?
    I thought it gives the wrong answer because of using remove_copy_if after the use of find_if becuase remove_copy_if uses another copy of the predicate to move the rest of the range.

    Am I on the right track here?
    "All that we see or seem
    Is but a dream within a dream." - Poe

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The idea is that the function object is copied from the original passed-in value when the algorithm restarts, rather than the "current" copy where count is 3. IOW, when you pass a function object with internal state into an algorithm, you can't rely on all the calls being done "in order"; the algorithm can decide to go back to the original version passed in (and therefore the original internal state) at a whim. In this case, it happens when it finds the first item to remove is found and the remove_if calls remove_copy_if -- a new copy of Nth(3) is started at that time. Since remove_copy_if doesn't restart, you only lose 3 and 6 (rather than 3, 6, and 9).

  3. #3
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    thank you for the concise explanation, tabstop.
    "All that we see or seem
    Is but a dream within a dream." - Poe

Popular pages Recent additions subscribe to a feed