Подтвердить что ты не робот

Почему std:: set.insert() возвращает не-const-итератор, и все же я не могу его изменить?

Рассмотрим этот пример кода:

#include <set>
#include <string>

using namespace std;

set<string> string_set;

void foo(const string& a)
{
    pair<set<string>::iterator, bool> insert_result = string_set.insert(a);

    string& val = *(insert_result.first);
    val += " - inserted";
}

Итак, исправление в сторону, например, не проверка успешной вставки и т.д., этот код выглядит так, что он должен позволять мне изменять строку после вставки, но компилятор (VS2010) запрещает разыменование итератора неконстантной строкой (мы переносимся с VS2005, который пропустил это без предупреждения).

Теперь я знаю, что это должно быть запрещено, так как это может сделать строку неповторимой, и я рад, что она работает таким образом, но в реальном мире это не совсем так ясно, как это, поскольку я хотите изменить неперемещаемый элемент данных, который не участвует в тестировании эквивалентности или заказе.

Что я хочу знать, как компилятор ЗНАЕТ, что мне не разрешено это делать, и как я могу узнать без ссылки на документацию (что вообще не упоминает об этом)?

Cheers, Гай

4b9b3361

Ответ 1

Потому что согласно стандарту, модификации через a set<>::iterator не допускаются. Стандарт специально позволяет set<>::iterator и set<>::const_iterator быть такой же тип. И хотя это не требует от них того же type, для этого требуется value_type set<>::iterator be const.

Причиной этого, конечно же, является то, что любые модификации значение может аннулировать инварианты std::set<>.

Ответ 2

Из стандарта:

23.3.3

Множество является своего рода ассоциативным контейнер, который поддерживает уникальные ключи (содержит не более одного ключа значение) и обеспечивает быстрый поиск самих ключей. Набор классов поддерживает двунаправленные итераторы.

Это также из стандарта:
  Определена реализация typedef   итератор;   // См. 23.1

Реальная реализация set:: iterator - это постоянный итератор, чтобы сохранить требование наличия уникальных ключей. В противном случае вы можете изменить значения в наборе на все те же значения.