0

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
jason adams
  • 545
  • 2
  • 15
  • 30

2 Answers2

1

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());
 }
Community
  • 1
  • 1
MicroVirus
  • 5,324
  • 2
  • 28
  • 53
  • Could you explain what a predicate is, is that related to the error that I posted? and will remove also work in the delete_even method? – jason adams Nov 06 '15 at 16:55
  • A predicate is just a fancy word for a 'function' that can return either `true` or `false`, based on its input. For instance, your `is_even` is a predicate. – MicroVirus Nov 06 '15 at 16:57
  • I think the issue is that you can't use a member function for a predicate. Unless it's the member function operator(). – Anon Mail Nov 06 '15 at 16:59
1

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

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • what is the auto for? don't variables default to auto? – jason adams Nov 06 '15 at 17:12
  • @jasonadams [`auto`](http://en.cppreference.com/w/cpp/language/auto) is a specifier that tells the compiler to deduce the correct type for the variable. What do you mean by *don't variables default to auto?* – NathanOliver Nov 06 '15 at 17:14
  • I didn't know what auto was used for so I went to this link: http://stackoverflow.com/questions/1046477/is-there-any-reason-to-use-the-auto-keyword-in-c03 – jason adams Nov 06 '15 at 17:18
  • 1
    @jasonadams Ah. Auto in C++11 and above is different. see: http://en.cppreference.com/w/cpp/language/auto – NathanOliver Nov 06 '15 at 17:20