user107986
user107986

Reputation: 1541

Why const is required when dereferencing std::set<T>::iterator?

I have the following code:

    std::set< std::vector<int> > testSet;
    vector<int> v0 = vector<int>(3);
    vector<int> v11 = vector<int>(3);
    v0[0] = 0;
    v0[1] = 10;
    v0[2] = 20;
    std::cout << v0[0] << endl;
    testSet.insert(v0);
    v0[0] = 1;
    v0[1] = 11;
    v0[2] = 22;
    testSet.insert(v0);
    std::set< std::vector<int> >::iterator it;

    for (it = testSet.begin(); it != testSet.end(); it++) {
        const std::vector<int>& i = (*it); 
        std::cout << i[0] << endl;  
    }

When I change:

const std::vector<int>& i = (*it)

to:

std::vector<int>& i = (*it)

it stops working. Apparently (*it) returns a const vector<int>&, but why is it the case? The set contains vectors, not const vectors.

Upvotes: 1

Views: 905

Answers (2)

engineerDon
engineerDon

Reputation: 11

I am providing a contradictory answer. The standard is overly presumptuous in saying that changing the object will change the order. I can easily have an object that itself has constant data that can be used for ordering AND non-constant data that doesn't have anything to do with its order within the set. My objects have a const std::string m_name that is used by my custom comparator for ordering, but has a whole slew of setters for changing other things about it.

Upvotes: 1

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48447

This is because your actual testSet declaration looks as follows:

std::set<std::vector<int>, std::less<std::vector<int>>> testSet;
//                         ~~~~~~~~~~~~~~~~~~~~~~~~~~^

That is, the value_type itself is used as the argument for ordering predicate (no matter if it is std::less<T> or a custom one), and its location within std::set data structure (possibly RB-tree) depends on its original value (at the time of insert operation). Thus, changing the content without reordering the std::set would break the ordering logic.

The constness of non-const iterator is also mentioned in the standard:

§ 23.2.4 Associative containers [associative.reqmts]

  1. iterator of an associative container is of the bidirectional iterator category. For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type.

Upvotes: 3

Related Questions