0

Suppose I have the following class

class Human
 {
public:
    Human();
    Human(string,int);
    virtual ~Human();
    string getName();

protected:

private:
    string name;
    int staj;
 };

I have created list with 2 elements that I pushed in

  list<Human> mylist;
  Human x ("Mike",13);
  Human y("pavlek",33);

I am trying to remove if there is element with name "Mike",I tried removing it like this :

   for(list<Human>::iterator it=mylist.begin();it!=mylist.end();++it)
  {


  if(it->getName()=="Mike")
  {
      mylist.remove(it);
      cout<< "removed";
       cout<<it->getName();
  }

}

However I get error at passing the value to the remove() function,what should I exactly pass in order to delete this element from the list?

Tejas Kale
  • 415
  • 8
  • 18
  • 1
    Consider using `` and the `erase`-`remove_if` idiom: https://stackoverflow.com/questions/39019806/using-erase-remove-if-idiom But if you don't, then at least cache your `end()` iterator! ;-) Alternatively, this answer shows a nicer way using `` to remove just the 1st matching element, if that's all you need: https://stackoverflow.com/questions/14737780/how-do-i-remove-the-first-occurrence-of-a-value-from-a-vector – underscore_d May 22 '17 at 23:40
  • https://stackoverflow.com/questions/3866642/stl-list-erase-items – pm100 May 23 '17 at 00:41

2 Answers2

2

You have simply mistaken erase and remove. According to the C++ reference, remove is used to remove from the list all elements whose values are equals to the given parameter. On the other hand, erase removes a single element given its position or a range of elements given the start and end positions.

If you only need to delete the first element containing "Mike" as its name, simply do something like this:

for(list<Human>::iterator it=mylist.begin();it!=mylist.end();++it)
{
    if(it->getName() == "Mike")
    {
        mylist.erase(it);
        break;
    }
}

Please notice that after using erase, your iterator will be invalidated. You can circumvent it by using the returned value of erase, which is the next valid iterator value. This detail is important if your list might contain multiple elements whose name is "Mike".

Matheus Portela
  • 2,420
  • 1
  • 21
  • 32
  • just to reiterate (pardon the pun) this code will not work. The iterator is invlaid after the erase – pm100 May 23 '17 at 00:40
0

Matheus Portela's solution was the old C++98 method. It's a lot easier now:

mylist.remove_if( [](Human const& h){return h.getName()=="Mike";} );

The condition here is [](Human const& h){return h.getName()=="Mike";}. That is a lambda expression which returns true if the Human h should be removed. You can test any other property or combination of properties there. The { } part of the lambda is a real function body; you could even have for-loops in there:

Other examples:

mylist.remove_if( [](Human const& h){return h.getName().size() > 4; } );

mylist.remove_if( [](Human const& h) {
     for (char c: h.getName())
         if (c=='i') return true; // remove if name contains an i
     return false; } );

Mind you, the latter would be easier with std::any_of.

MSalters
  • 173,980
  • 10
  • 155
  • 350