在C++ 17中,为什么关联容器有一个`erase`成员函数,它接受(非`constst`)`iterator`?

Bri*_*ian 12 c++ iterator stdmap const-iterator c++17

参见,例如, 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 );
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,第一和第二过载改变为采取const_iterator,使得它们可与任一被调用iteratorconst_iterator.第一次重载也通过在删除之后将迭代器返回到元素来改进:

iterator erase( const_iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );
Run Code Online (Sandbox Code Playgroud)

在C++ 17中,重新引入了非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 );
Run Code Online (Sandbox Code Playgroud)

为什么需要这个?它不加入为不等erase,也不是为insert,也不对任何序列的容器如vector,deque,和list.

Pra*_*ian 15

这样做是为了解决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);
}
Run Code Online (Sandbox Code Playgroud)

到呼叫map::erase,因为两者在末端是不明确的map::erase(const_iterator)并且map::erase(key_type const&)同样良好的匹配,而它们的每个需要用户定义的转换.

重新引入map::erase(iterator)过载可以解决这个问题.