Compile error with nested loops & iterators

Hi all, I have a problem here, with a type like set<vector<int> > and iterators running through both levels:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <set>
#include <vector>

using namespace std;

int main() {
    typedef vector<int> V;
    typedef set<V> S;

    S s;
    V v;
    v.push_back(0);
    v.push_back(1);
    s.insert(v);

    S::iterator sit;
    V::iterator vit;
    V vtemp;

    // this works
    for (sit = s.begin(); sit != s.end(); sit++) {
        vtemp = *sit;
        for (vit = vtemp.begin(); vit != vtemp.end(); vit++) {
            cout << *vit << " ";
        } 
        cout << endl;
    }

//     // doesn't compile: no matching found: operator= ...
//     for (sit = s.begin(); sit != s.end(); sit++) {
//         for (vit = sit->begin(); vit != sit->end(); vit++) {
//             cout << *vit << " ";
//         } 
//         cout << endl;
//     }

//     // neither does this work
//     for (sit = s.begin(); sit != s.end(); sit++) {
//         for (vit = (*sit).begin(); vit != (*sit).end(); vit++) {
//             cout << *vit << " ";
//         } 
//         cout << endl;
//     }

//     // ok, this shouldn't work, need to 'dereference' iterator
//     for (sit = s.begin(); sit != s.end(); sit++) {
//         for (vit = sit.begin(); vit != sit.end(); vit++) {
//             cout << *vit << " ";
//         } 
//         cout << endl;
//     }


    return 0;
}


Using this temporary variable, the assignment works fine, but when using it directly, I get compiler errors.

g++ 4.3.3 gives (after uncommenting the second loop):
1
2
bla.cpp:32: error: no match for β€˜operator=’ in β€˜vit = sit.std::_Rb_tree_const_iterator<_Tp>::operator-> [with _Tp = std::vector<int, std::allocator<int> >]()->std::vector<_Tp, _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]()’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.3/../../../../include/c++/4.3.3/bits/stl_iterator.h:666: note: candidates are: __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >& __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >::operator=(const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)


g++ 3.4.6 gives:
 
error: invalid conversion from `const int* const' to `int*'


Any ideas? I'd really like to understand the problem here. Maybe it's an error within g++. Could someone try another compiler (and uncomment the stuff)?
Your type system makes me nauseous.

Change the types of sit and vit to *::const_iterator.
Thanks for the quick answer.

Using const_iterators here works with both compiler versions (and makes more sense in this situation), but why does the first version with the temporary vector<int> still work. Is it generally impossible/forbidden to use normal iterators here?

The type(name)s used are just there to provide a minimal failing example, of course.

Update: OK, the assignment of the temporary variable actually copies the vector and prints out these values, I see it now.
Last edited on
It would seem dereferencing any iterator (both const and non-const) returns a const reference, and using begin() on that reference returns therefore a const_iterator, which of course can't be assigned to a non-const_iterator.

Hey, I learnt something new!
Last edited on
set<>::iterator is the same as set<>::const_iterator. The container cannot allow you to modify an element of it through an iterator since doing so may break the container's invariant (the sort order and the uniqueness of all elements).

Topic archived. No new replies allowed.