const_iterator

Write your question here.
hello, everyone, I would like to know why passing a const_iterator to an iterator parameter of a function does not cause errors in compiling and running.
In the following code, I passed the C.begin() to the second parameter of inser_iterator<set<string> > constructor, (C is set<string> type). C.begin() returns a const_iterator since set is const, but the second parameter of insert_iterator constructor is iterator type.
passing a const_iterator to an iterator and no error generated, What happened here ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <iterator>
int main()
{
    using namespace std;
    const int N = 6;
    string s1[N] = { "buffoon", "thinkers", "for", "heavy", "can", "for" };
    string s2[N] = {  "metal", "any", "food", "elegant", "deliver", "for" };

    set<string> A(s1, s1 + N);
    set<string> B(s2, s2 + N);

    set<string> C;
    set_union(A.begin(), A.end(), B.begin(), B.end(), insert_iterator<set<string> >(C, C.begin()));

    cout << "Set C:\n";
    ostream_iterator<string, char> out(cout, " ");
    copy(C.begin(), C.end(), out);
    return 0;
}
C.begin() returns a const_iterator since set is const

Nope.
https://en.cppreference.com/w/cpp/container/set/begin
Last edited on
Where do you see any const? C is not and cannot be const.
S1, S2, A, B can be declared const, giving:

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
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
	const int N {6};

	const string s1[N] {"buffoon", "thinkers", "for", "heavy", "can", "for"};
	const string s2[N] {"metal", "any", "food", "elegant", "deliver", "for"};

	const set<string> A(s1, s1 + N);
	const set<string> B(s2, s2 + N);

	set<string> C;

	set_union(A.cbegin(), A.cend(), B.cbegin(), B.cend(), insert_iterator<set<string> >(C, C.begin()));
	cout << "Set C:\n";

	ostream_iterator<string, char> out(cout, " ");
	copy(C.begin(), C.end(), out);
	return 0;
}

Thank you all, first.

Since the elements in the container can not be modified(except insert or remove), I thought the iterator returned by C.begin() is const_iterator type but it is not in fact.

Now, it makes senses to some degree. Passing an iterator to another will not cause errors.
But further, I am still a little confused by another problem caused by this explanation.

When I learn pointers, for example, if the returned value is of const char * type , the returned type must be const char * too. If not, compile failed.

Here the element inside the set is constant, which can not be modified. If the definition is similar to pointers, the returned value by C.begin() should be of const_iterator type but it doesn't.

So I guess the definition of iterator and const_iterator for set are the same like the following:

template<class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>
class set;
...
class iterator // the difference between the iterator and const_iterator is only the class name
{
const Key * it;
public:
iterator(const Key * p) : it(p) {}
const Key & operator*() {return *it;} // since we can not modify *it
const Key * operator++() {return ++it;}
...
};
iterator begin()
{
return &set[0];
}
...

I would like to know if this is correct. Thank you for correcting it in advance.
If it is totally wrong, please also point it out and give an explanation. (just for example, if the private member of iterator should be (Key * it) not (const Key * it), please explain why.)
> So I guess the definition of iterator and const_iterator for set are the same like the following
> I would like to know if this is correct.

Yes, this is correct. Both iterator and const_iterator for std::set iterate over constant (immutable) values.

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.

[Note 2: iterator and const_­iterator have identical semantics in this case, and iterator is convertible to
const_­iterator. Users can avoid violating the one-definition rule by always using const_­iterator in their function parameter lists. — end note]
https://eel.is/c++draft/container.requirements#associative.reqmts.general-6
Thanks JLBorges. Now I get it.
Topic archived. No new replies allowed.