Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++17, why do associative containers have an `erase` member function that takes (non-`const`) `iterator`?

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.

like image 818
Brian Bi Avatar asked Dec 21 '16 06:12

Brian Bi


People also ask

What is an associative container in C?

In computing, associative containers refer to a group of class templates in the standard library of the C++ programming language that implement ordered associative arrays. Being templates, they can be used to store arbitrary elements, such as integers or custom classes.

How many associative containers are provided by C Plus Plus?

Types of Sequence Containers In the C++ Standard Library, there are four ordered associative containers and four unordered associative containers. The four ordered associative containers are multiset, set, multimap, and map.

Why Is set an associative container?

Sets are a type of associative container in which each element has to be unique because the value of the element identifies it. The values are stored in a specific sorted order i.e. either ascending or descending.


1 Answers

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.

like image 53
Praetorian Avatar answered Sep 18 '22 20:09

Praetorian