2015-05-14 4 views
1

Я использую Visual Studio 2013 для компиляции очень простой код:Почему std :: remove принимает версию итераторов const?

std::set<int> a{ 1, 2, 3 }; 
std::remove(a.begin(), a.end(), 3); 

Я ожидаю, что это не может пойти не так, но я удивлен. Ошибка испускает:

Error 1 error C3892: '_Next' : you cannot assign to a variable that is const c:\program files (x86)\microsoft visual studio 12.0\vc\include\algorithm 

Как это может быть? a является неконстантным std :: set. std :: remove() перемещает элемент и выглядит совершенно законным.

В VS 2008, ниже аналогичный код компилируется без ошибок:

std::set<int> a; 
std::remove(a.begin(), a.end(), 3); 

ответ

4

Множества является неконстантным но set::begin(), set::end() возвращает const_iterator. Как видно, on cppreference.

Я считаю, что это должно избегать «аутсайдеров», способных менять элементы вокруг, поскольку один из инвариантов множества состоит в том, что все элементы сортируются (это именно то, что делает std::remove, оно перемещает элементы вокруг так, что вы можете называть их стиранием впоследствии см. erase-remove idiom)

Если вы хотите удалить элемент, используйте функцию erase.

+0

Да, я замечаю это поведение. Он отличается от VS 2008. В VS 2008 код компилируется. – Sheen

+0

@Sheen это изменение в самом стандарте C++. –

+0

P.S. Я не люблю изменения. Раньше вы могли сделать объект с ключевой частью, и до тех пор, пока вы не изменили ключ, вы могли бы модифицировать остальную часть объекта по мере необходимости. Это больше не разрешено. –

0

std::remove предназначено для линейных контейнеров, таких как vector и list, не отсортированные контейнеры, такие как set. (Учтите: remove свопы элементов Что бы это даже значит поменять местами элементы set.?)

Это звучит, как вы хотите std::set::erase.

Смежные вопросы