В C++17 почему ассоциативные контейнеры имеют функцию-член "erase", которая принимает (не "const") "итератор"?

см., например,http://en.cppreference.com/w/cpp/container/map/erase

в C++03 было три перегрузки:

void erase( iterator pos );
void erase( iterator first, iterator last );
size_type erase( const key_type& key );

в C++11 первая и вторая перегрузки были изменены на take const_iterator чтобы их можно было назвать либо iterator или const_iterator. Первая перегрузка также была улучшена, когда она вернула итератор элементу после стирания:

iterator erase( const_iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );

в C++17 перегрузка non-const был вновь представлен:

iterator erase( const_iterator pos );
iterator erase( iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );

зачем это нужно? Он не был добавлен для ranged erase, ни insert, ни для любого из контейнеров последовательности, таких как vector, deque и list.

1 ответов


Это было сделано по решению lwg дефект 2059. Рассмотрим пример из ссылки

#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);
}

вызов map::erase в конце неоднозначно, так как map::erase(const_iterator) и map::erase(key_type const&) одинаково хорошие совпадения, поскольку каждый из них требует определенного пользователем преобразования.

возвращение map::erase(iterator) перегрузка устраняет эту проблему.