Why const_iterator could be used with std::map::erase

1.4k views Asked by At

I was under the impression one cant use erase on a const iterator. Check this code.
Why does the below code compile (C++11, gcc)?

long getMax(const bool get_new)
{
    long max_val=0;

    TO now=getNow();

    map<TO, long>& m=get_new?m_new:m_old;

    for(auto it=m.cbegin(); it !=m.cend())
    {
        if(now.compareTime((*it).first)<lookback)
        {
            max_val=max(max_val,
                        (*it).second);
            ++it;
        }
        else
        {
            it=m.erase(it);
        }
    }

    return max_val;
}

The map itself is not constant, but my understanding is that the const iterator should make this fail.

2

There are 2 answers

0
leslie.yao On BEST ANSWER

The behavior has changed from C++11; std::map::erase takes const_iterator as its parameter.

void erase( iterator pos );           // (until C++11)
iterator erase( const_iterator pos ); // (since C++11)
iterator erase( iterator pos );       // (since C++17)

For std::map::erase, the passed iterator is just used as the position where the element would be deleted, not for modifying the element through it. That means const_iterator would be fine. Before C++11, the support for const_iterator was not very good, but the situation has changed from C++11. You should use const_iterator instead of iterator when possible now.

0
Dietmar Kühl On

Positions are independent of the constness of their access. It was (is?) quite common that functions doing a search return const_iterator because they actually do not change the container at all. However, it is desirable to use the obtained position for mutations of the sequences, e.g., to insert() an element at the corresponding position or to erase() the located element. As a result, the container where extended to support use of const_iterator with mutating operations.

It seems the relevant paper is N2350. I'm not sure if this paper is the latest version.