365sleeping
365sleeping

Reputation: 1

Remove a list item from list in the item's member function

Say I have a list list<Item>, and

class Item {
 public:
  Item(list<Item>& l); // l is the list the item is in.

  RemoveItself() {...} // remove this from l.
}

When I call item.RemoveItself(), it removes itself from the list. If I were to implement this myself, I could have prev_ptr and next_ptr in the Item, and then everything is easy. I am wondering if there is a way to do it using STL?

Upvotes: 0

Views: 155

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596287

Your list is holding Item objects, which are going to be copies of any Items you insert into the list. As such, you would have to use std::find_if() and list::erase(), or list::remove_if(), to remove elements that compare equal to *this, eg:

class Item {
private:
  list<Item> &l;

public:
  Item(list<Item> &l) : l(l) {}

  void RemoveItself() {
    auto iter = std::find_if(l.begin(), l.end(),
      [this](const Item &elem){
        return true/false based on some condition of elem and this representing the same item...;
      }
    );
    if (iter != l.end())
      l.erase(iter);

    // or:
    l.remove_if(
      [this](const Item &elem){
        return ...;
      }
    );
  }
};

Which probably isn't what you want. A list of Item* pointers would probably be more appropriate instead (list<Item*>), eg:

class Item {
private:
  list<Item*> &l;

public:
  Item(list<Item*> &l) : l(l) {}

  void RemoveItself() {
    auto iter = std::find(l.begin(), l.end(), this);
    if (iter != l.end())
      l.erase(iter);

    // or:
    l.remove(this);
  }
};

In which case, if the Item() constructor adds this to the list, then it can also save an iterator to the new element, and then it can simply remove that element later:

class Item {
private:
  list<Item*> &l;
  list<Item*>::iterator l_iter;

public:
  Item(list<Item*> &l) : l(l) { l_iter = l.insert(l.end(), this); }

  void RemoveItself() {
    l.erase(l_iter);
  }
};

Upvotes: 2

Related Questions