Is it possible to remove an element from an std::list if you have only the iterator that points to the element you want to remove? I have a large amount of functions that take iterators to list elements, and it would be a huge inconvenience to have to pass the owning list to every one of them.
6 Answers
Edit:
You cant with a single iterator.
If you have the begin/end iterators, you could use the std::remove algorithm to move all the elements you want to erase to the end, and delete them at a later point.
If you don't, or the above isn't feasible with your current design, i'd recommend altering your functions to take a std::pair<std::list<T>, std::list<T>::iterator> or something like that.
5 Comments
std::remove() function does not remove items from the container, because it just can't. Check out the erase-remove idiom.std::pair one), so I'll mark this as the answer.std::remove() does not necessarily move the objects to be removed to the end. It makes no claims as to what happens to them. For std::vector, I'm sure all implementations will just overwrite them. For std::list I'm not sure.No, you can't. Iterators are light-weight objects modeled after pointers and do not carry a reference to the container they refer to. (Although some implementations do so internally in Debug mode.)
Just as you cannot "remove" an object from an array when all you have is a pointer into the array, you cannot remove an object from a container without also having access to the container.
Comments
You can't do that with the standard library, but you can use Boost's intrusive list http://www.boost.org/doc/libs/1_37_0/doc/html/boost/intrusive/list.html which has such an interface.
Comments
While others have mentioned that you can't do it, I think I can offer as to why.
I believe the specific technical reason (rather than design reason) is that lists do some upkeep, like keeping track of size for example, which require that certain actions have to be passed through them to allow that upkeep.
It's for this reason that any hack that might be offered would likely fail.
1 Comment
No, this is not possible. As its name suggests, an iterator's job is to iterate over the elements of a sequence. Check out the SGI page on iterators for a summary of iterator design in the C++ standard library.
3 Comments
list is a doubly-linked list, could you not write a function to manipulate the next and previous pointers so that it removes the element? Or would that be really bad? Or is it just that the members are private?You can do this manually. iterator exposes _M_node as the current node. you can do something like:
itr._M_node->_M_prev->_M_next = itr._M_node._M_next; 3 Comments
_M_prev pointer of _M_next (because it's a dlinked list). That's something I was thinking of, but this code needs to work with different versions/compilers as well.size() and O(1) splice()).
listwhich doesn't invalidate other iterators if you remove an item from it. Also @nj, I don't think that's relevant to this question.