See, e.g., http://en.cppreference.com/w/cpp/container/map/erase
In C++03 there were three overloads:
void erase( iterator pos );
void erase( iterator first, iterator last );
size_type erase( const key_type& key );
In C++11, the first and second overloads were changed to take const_iterator so that they could be called with either iterator or const_iterator. The first overload was also improved by having it return the iterator to the element after the one erased:
iterator erase( const_iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );
In C++17, a non-const overload was re-introduced:
iterator erase( const_iterator pos );
iterator erase( iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );
Why is this needed? It was not added for the ranged erase, nor for insert, nor for any of the sequence containers such as vector, deque, and list.
                        
This was done to address LWG defect 2059. Consider the example from the link
The call to
map::eraseat the end is ambiguous because bothmap::erase(const_iterator)andmap::erase(key_type const&)are equally good matches as they each require a user defined conversion.Reintroducing the
map::erase(iterator)overload fixes this problem.