3

I'm creating an API which users will call to remove items from an internal vector. They will pass in criteria to search the vector for elements to remove. I'd like my API to return a boolean for if any elements were found and removed.

I'm planning on using the erase-remove idiom to keep things simple and efficient. I don't see an obvious way right off to detect that items were actually removed? Is storing the number of elements in the vector before removing, and comparing the value, my best bet?

Here is some (untested) sample code on this idiom:

std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

boolean removeMultiples(int multiple) {
    v.erase( std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;}), v.end() );
    // return true if anything was removed
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Brad
  • 5,492
  • 23
  • 34

3 Answers3

8

One idea would be to store the return value of std::remove_if, and compare it with the containers end() iterator before doing the erase like this:

bool removeMultiples(int multiple)
{
    auto it = std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;});
    bool any_change = it != v.end();
    v.erase(it, v.end());
    return any_change;
}
Fatih BAKIR
  • 4,569
  • 1
  • 21
  • 27
  • I would take a lambda instead of hardcoding it. Then have remove multiples call it. – Yakk - Adam Nevraumont May 24 '17 at 22:36
  • @Yakk, do you mean the `remove_if` predicate? If so you're right, and it should probably be a template parameterised on the container type and the predicate, but I just wanted to answer in the questions context. – Fatih BAKIR May 24 '17 at 23:24
4

There is no need to write the algorithms in one line. You can for example write

bool removeMultiples( int multiple )
{
    bool success;

    auto it = std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;});

    if ( ( success = it != v.end() ) ) v.erase( it, v.end() );

    return success;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0
template<class C, class F>
bool remove_some(C&c, F&&f){
  using std::begin; using std::end;
  auto it = std::remove_if(begin(c), end(c), std::forward<F>(f) );
  bool r = it!=end(c);
  c.erase(it, end(c));
  return r;
}

then

bool removeMultiples(std::vector<int>& f, int multiple) {
  return remove_some(v, [multiple](int i){return !(i%multiple);});
}

is simple and clean.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524