Assignment of read-only location while using set_union to merge two sets

Viewed 642

I am trying to combine two set to one set, but when I use the simplest example, a error:assignment of read-only location '__result.std::_Rb_tree_const_iterator<_Tp>::operator*<int>()' the code is:

set<int> a;
set<int> b;
int x[4] = {0,1,2,3};int y[5] = {1,2,4,6,9};
a.insert(x,x+4);
b.insert(y,y+5);
set<int> c;
set_union(a.begin(), a.end(), b.begin(), b.end(), c.begin());

So am I writing wrong? What should I do if I want to merge two set and use a new set to contain the elements?

The error calls from this line: set_union(a.begin(), a.end(), b.begin(), b.end(), c.begin());

1 Answers

std::set<int>::iterator isn't an OutputIterator, so it isn't suitable for use as the fifth argument of std::set_union. You probably mean to insert into c, so a suitable iterator is std::inserter(c,c.begin()).

set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(c,c.begin()));

An OutputIterator is one that can have its pointed-to values assigned to, and a std::insert_iterator<std::set<int>> achieves this by returning a proxy object, that inserts into the set when assigned to, rather than a int&

Alternatively, if you know how many items will result (or are prepared to overallocate), you could use a different container's begin, such as std::array<int, 7>, or a std::vector<int> whose size was sufficient to contain the 7 elements resulting from the union.

std::vector<int> d(a.size() + b.size(), 0); // preallocate enough
std::vector<int>::iterator end = std::set_union(a.begin(), a.end(), b.begin(), b.end(), d.begin());
d.erase(end, d.end()); // clean up any excess elements not from `a` or `b`
Related