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
#include <map>
struct X
{
template<typename T>
X(T&) {}
};
bool operator<(const X&, const X&) { return false; }
void erasor(std::map<X,int>& s, X x)
{
std::map<X,int>::iterator it = s.find(x);
if (it != s.end())
s.erase(it);
}
The call to map::erase
at the end is ambiguous because both map::erase(const_iterator)
and map::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.