Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::set.insert() return a non-const iterator, and yet I cannot modify it?

Consider this code example:

#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";
}

So, correctness aside, such as not checking for successful insertion and so on, this code looks like it should allow me to amend the string after insertion, but the compiler (VS2010) forbids dereferencing the iterator to a non-const string (we're migrating from VS2005 which waved this through without a warning).

Now, I know this should be forbidden since it may make the string non-unique, and I'm kind of glad it works this way, but in the real world case it's not quite so clear cut as that, as I want to amend a non-mutable data member that doesn't participate in equivalence testing or ordering.

What I want to know is, how does the compiler KNOW I'm not allowed to do this, and how do I know without reference to the documentation (which doesn't mention this anyway)?

Cheers, Guy

like image 882
hatcat Avatar asked Apr 12 '11 07:04

hatcat


2 Answers

Because according to the standard, modifications through a set<>::iterator are not allowed. The standard specifically allows set<>::iterator and set<>::const_iterator to be the same type. And although it doesn't require them to be the same type, it does require the value_type of set<>::iterator to be const.

The reason for this, of course, is that any modifications to the value could invalidate the invariants of std::set<>.

like image 110
James Kanze Avatar answered Oct 06 '22 00:10

James Kanze


From the standard :

23.3.3

A set is a kind of associative container that supports unique keys (contains at most one of each key value) and provides for fast retrieval of the keys themselves. Class set supports bidirectional iterators.

This is also from the standard :
typedef implementation defined iterator; // See 23.1

The real implementation of set::iterator is a constant iterator in order to keep the requirement to have unique keys. Otherwise you could change the values in set to all the same values.

like image 32
BЈовић Avatar answered Oct 05 '22 22:10

BЈовић