c++std-pairerase-remove-idiom

How to remove from vector of pairs the value item from pair that is a class in c++?


i am trying to remove all Orders that have old pizza than 3 days :

i have this vector of pairs :

 std::vector<std::pair<Client,Order>> x;
    x.push_back(std::make_pair(Client(2,"Anca"),Order(3,1)));
    x.push_back(std::make_pair(Client(16,"Maria"),Order(1,3)));
    x.push_back(std::make_pair(Client(29,"Alex"),Order(10,5)));

and this class Order:

class Order{
private:
    int amountPizza;
    int pizzaAge;
public:
int getPizzaAge(){
        return pizzaAge;
    }

and i did something like this :

auto it=x.begin();
   while(it!=x.end()){
        if((it->second).getPizzaAge()>3){
            x.erase(std::remove(x.begin(),x.end(),it->second),x.end());
        }
        it++;
    }

and is not working.

Errors:

error: no match for 'operator==' (operand types are 'std::pair<Client, Order>' and 'const Order')
  { return *__it == _M_value; }
 'std::pair<Client, Order>' is not derived from 'const __gnu_cxx::__normal_iterator<_IteratorL, _Container>'
  { return *__it == _M_value; }

Solution

  • Using extra while loop is wrong. The moment you erase first element, end() iterator is invalidated. Fortunately, std::remove (and std::remove_if) can handle any number of elements in a single call.

    The second issue is that std::remove can only be used for removing exactly same elements (compared with operator ==). However, using std::remove_if you can provide a comparison function that is more flexible.

    Your code should look like this:

    auto newEnd = std::remove_if(x.begin(), x.end(), [](const auto& p) {
        return p.second.getPizzaAge() > 3;
    });
    x.erase(newEnd, x.end());