0
votes

Prior to using remove_if, I was using remove. So say if I had vec = {1, 2, 2, 2, 5}, and wanted to remove all 2s, I would do:

for (vector<int>::iterator it = vec.begin(); it!= vector.end(); ++it){
    if (*it == 2){
       vec.erase(remove(vec.begin(),vec.end(), *it), vec.end());
    }
}

This will not work as it's not possible and illogical to iterate through a vector as deletion is being done.

So then I discovered remove_if(). However, for some reason I can't get it to work within the context of a class. Here's my code:

class SomeClass{
    private:
       vector<int> vec;
    public:
       SomeClass(){
           //initalizae vec to {1,2,2,2,4,5,6,8}
       }
       bool is_even(int value){
           return value % 2 == 0;
       }
       void delete(int a){
           vec.erase(remove_if(vec.begin(), vec.end(), a), vec.end());
       }
       void delete_even(int a){
           vec.erase(remove_if(vec.begin(), vec.end(), this->is_even(a)), vec.end());
       }

I am guessing void delete will not work because a is an int and I need a bool value, but not sure how to express "if int a is in this vector return true" as the third parameter for remove_if. And I'd expect void delete_even to work but I get

note: in instantiation of function template specialization 'std::__1::remove_if<std::__1::__wrap_iter<int *>, bool>' requested here
2
void delete(int a) is insaneuser2249683
Why are you erasing the return of remove_if ??YSC
@YSC Because that's how it works with iterators and remove. Confusing, but true.MicroVirus
@MicroVirus That's true, my bad. End of the week here ;)YSC

2 Answers

1
votes

If you just want to remove some value from the vector than you can just use remove()

foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());

If you want to remove all even numbers then instead of using a class member function I would suggest using a lambda.

foo.erase(std::remove_if(foo.begin(), foo.end(), [](auto n) { return n % 2 == 0;}), foo.end());

Here is an example using both approaches

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

int main()
{
    std::vector<int> foo = {1,2,3,4,5,6,7,8,9};
    // remove all even numbers
    foo.erase(std::remove_if(foo.begin(), foo.end(), [](auto n) { return n % 2 == 0;}), foo.end());
    for (auto e : foo)
        std::cout << e << std::endl;
    std::cout << std::endl;
    // remove all elemenets that match some_value
    foo = {1,2,2,2,2,2,7,8,9};
    int some_value = 2;
    foo.erase(std::remove(foo.begin(), foo.end(), some_value), foo.end());
    for (auto e : foo)
        std::cout << e << std::endl;
}

Output:

1
3
5
7
9

1
7
8
9

Live Example

1
votes

Just use std::remove to remove an int value from the collection, without searching for it yourself:

vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());

This will remove all occurrences of 2 from vec.

The usage of remove_if is the same, only then rather than an element you give a predicate (typically a function); if C++11 is available to you, you can use it with a lambda as such:

vec.erase(std::remove_if(vec.begin(), vec.end(), [](int a) {return a % 2 == 0;}), vec.end());

If you want to use is_even as a predicate to remove_if (or another member function of your class), then as mentioned in the comments, you should make it a static member function, preferably. You can also bind to non-static members, but there's no real reason to do that here; but see Using std::bind with member function, use object pointer or not for this argument? if you're curious, the question itself contains the correct syntax. A sample for is_even as static:

 static bool is_even(int value) {
     return value % 2 == 0;
 }

 void delete_even(int a){
     vec.erase(remove_if(vec.begin(), vec.end(), is_even), vec.end());
 }