Why is erasing via a const_iterator allowed in C++11?

761 views Asked by At

As of GCC 4.9.2, it's now possible to compile C++11 code that inserts or erases container elements via a const_iterator.

I can see how it makes sense for insert to accept a const_iterator, but I'm struggling to understand why it makes sense to allow erasure via a const_iterator.

This issue has been discussed previously, but I haven't seen an explanation of the rationale behind the change in behaviour.

The best answer I can think of is that the purpose of the change was to make the behaviour of const_iterator analogous to that of a const T*.

Clearly a major reason for allowing delete with const T* is to enable declarations such as:

const T* x = new T;
....
delete x;

However, it also permits the following less desirable behaviour:

int** x = new int*[2];
x[0] = new int[2];
const int* y = x[0];
delete[] y; // deletes x[0] via a pointer-to-const

and I'm struggling to see why it's a good thing for const_iterator to emulate this behaviour.

2

There are 2 answers

2
Ben Voigt On BEST ANSWER

erase and insert are non-const member functions of the collection. Non-const member functions are the right way to expose mutating operations.

The constness of the arguments are irrelevant; they aren't being used to modify anything. The collection can be modified because the collection is non-const (held in the hidden this argument).

Compare:

template <typename T>
std::vector<T>::iterator std::vector<T>::erase( std::vector<T>::const_iterator pos );
                                                                ^^^^^ ok

to a similar overload that is NOT allowed

template <typename T>
std::vector<T>::iterator std::vector<T>::erase( std::vector<T>::iterator pos ) const;
                                                                         wrong ^^^^^
0
AnT stands with Russia On
  1. The first question here is whether constness of an iterator is supposed to imply constnes of the entire container or just constness of the elements being iterated over.

    Apparently, it has been decided that the latter is the right approach. Constness of an iterator does not imply constness of the container, it only implies constness of container's elements.

  2. Since the beginning of times, construction of an object and its symmetrical counterpart - destruction of an object - were considered meta-operations with regards to the object itself. The object has always been supposed to behave as mutable with regard to these operations, even if it was declared as const. This is the reason you can legally modify const objects in their constructors and destructors. This is the reason you can delete an object of type T through a const T * pointer.

Given the resolution referred to by 1, it becomes clear that 2 should be extended to iterators as well.