What is the safe equivalent of erasing a non-void STL?

Suppose I have hash_map and code like

// i is an iterator i = hash_map.erase(i) 

But the GCC STL does not return the iterator to erase, but a void. Now this is a type code

 hash_map.erase(i++) 

safe (i.e. doesn't invalidate an iterator or any other unexpected or unpleasant things)? Please note that this is hash_map.

+4
source share
3 answers

Yes, it is safe, because the value of i will be set to the next value before the current value is erased.

According to the SGI documentation on hash containers, voidness does not occur for non-erased elements or even for resizing (there is no word in whether inserts cause resizing, so to be careful, I admit this as an opportunity), but in the latter case the order the iteration will be changed. But this is not applicable here unless you go out of your way to resize the container during a crawl or something else. :-)

+6
source

You can encapsulate erasure to provide the same interface for all containers you use:

 namespace detail { template<typename Container, typename R> struct SelectErase { // by default, assume the next iterator is returned template<typename Iterator> Iterator erase(Container& c, Iterator where) { return c.erase(where); } }; // specialize on return type void template<typename Container> struct SelectErase<Container, void> { template<typename Iterator> Iterator erase(Container& c, Iterator where) { Iterator next (where); ++next; c.erase(where); return next; } }; template<typename I, typename Container, typename R> SelectErase<Container,R> select_erase(R (Container::*)(I)) { return SelectErase<Container,R>(); } } // namespace detail template<typename Container, typename Iterator> Iterator erase(Container& container, Iterator where) { return detail::select_erase<Iterator>(&Container::erase).erase(container, where); } 

This requires either:

  • c.erase returns an iterator for the next element. Here's how the vector, deque, and list work.
  • c.erase returns void and does not invalidate the next iterator. This is how map, set and (non-stdlib) hash_map work.
+2
source

I hate rain in the parade, but I don’t think you are offering it safely.

i ++ is a post-increment statement, which means that I am incremented after a call to erase. But erasing invalidates all iterators pointing to the element to be erased. Therefore, by the time I increase, it is no longer valid.

If you're lucky, it may work correctly by accident until one day is gone.

As far as I know, this is not the case, but something like:

 // tmp and i are both iterators tmp = i; ++i; hash_map.erase(tmp); 
-4
source

All Articles