1

I am trying to remove elements from a vector of ints using std::remove_if, but am not getting the required output.

Initial vector members: {0, 1, 2, 1, 3, 1, 4, 5, 1, 6, 1, 7, 1, 8, 1, 9}

Required Output: {0, 2, 3, 4, 5, 6, 7, 8, 9}

Actual Output: {0, 2, 3, 4, 5, 6, 7, 8, 9, 6, 1, 7, 1, 8, 1, 9}

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <functional>

    class Equal
    {
    public:
    Equal(int a): a_(a){}
    bool operator()(int b)
    {
    return a_ == b;
    }
    
    private:
    int a_;
    };
    
    int main()
    {
    std::vector<int> vi{0, 1, 2, 1, 3, 1, 4, 5, 1, 6, 1, 7, 1, 8, 1, 9};
    
    std::cout << std::endl;
    std::remove_if(vi.begin(), vi.end(), Equal(1));
    for (const auto &i : vi) std::cout << i << " ";
    return 0;
    }
ss-haze
  • 13
  • 3

1 Answers1

3

There are just as many elements in the vector before and after the call to std::remove_if:

Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range.

... and std::remove_if returns an iterator to the start of the "removed" elements and you can use that iterator to actually erase the elements: See Erase–remove idiom

vi.erase(
    std::remove_if(vi.begin(), vi.end(), Equal(1)), // returns iterator
    vi.end()                                        // erase to the end
);

Demo

Also note that std::vector got a new specialized function in C++20 that does both things, namely std::erase_if.

Example:

std::erase_if(vi, Equal(1));
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Just to explain a little further: standard iterators don't support erasing elements from the container, so `std::remove_if` couldn't erase the elements if it wanted to. So we have to do that afterwards as shown in this answer. It also turns out this is a pretty efficient way of erasing elements, particularly for linear memory as with a vector. – Ken Wayne VanderLinde Mar 22 '21 at 22:31
  • Might help to mention that even though the number of elements are same after the call to `std::remove_if` they may not be the same elements. After the returned iterator there is essentially 'garbage'. In the question we can see 9 twice for example. – wally Mar 22 '21 at 22:32
  • Thank you very much Ted. – ss-haze Mar 22 '21 at 22:33
  • @ss-haze You're welcome! – Ted Lyngmo Mar 22 '21 at 22:40