Почему const_iterator может использоваться с std:: map:: erase

У меня было впечатление, что нельзя использовать erase на const iterator. Проверьте этот код.
Почему компилируется ниже код (С++ 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;
}

map сам по себе не является постоянным, но я понимаю, что const iterator должен сделать это сбой.

Ответы

Ответ 1

Поведение изменилось с С++ 11; std:: map:: erase принимает в качестве параметра const_iterator.

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

Для std::map::erase переданный итератор просто используется как позиция, в которой элемент будет удален, а не для изменения элемента через него. Это означает, что const_iterator будет в порядке. До С++ 11 поддержка const_iterator была не очень хорошей, но ситуация изменилась с С++ 11. Вы должны использовать const_iterator вместо iterator, когда это возможно.

Ответ 2

Позиции не зависят от их доступа. Было (есть?) Довольно часто, что функции, выполняющие поиск, возвращают const_iterator, потому что они фактически не меняют контейнер вообще. Однако желательно использовать полученную позицию для мутаций последовательностей, например, до insert() элемента в соответствующем положении или erase() расположенного элемента. В результате контейнер, который был расширен для поддержки использования const_iterator с мутировавшими операциями.

Кажется, что соответствующая статья N2350. Я не уверен, что этот документ является последней версией.