В 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)
перегрузка устраняет эту проблему.