Search code examples
c++setstl-algorithm

std::set difference with self defined type


I've defined my own struct like

struct element {

int id;
float value;
}

and I'm using it with std::set. I want to use the set_difference algorithm (like already mentioned in a previous question for determining the difference of two sets. When I try to invoke the code, compilation stops with the following error message:

/usr/include/c++/4.2.1/bits/stl_algobase.h:268: error: passing 
'const element' as 'this' argument of 'element& element::operator=(const element&)' 
discards qualifiers

A minimal example may look like this:

std::set<struct element> s1;
std::set<struct element> s2;
std::set<struct element> s3;

element e1 = { 1, 11.0 };
element e2 = { 2, 22.0 };
element e3 = { 3, 33.0 };

s1.insert(e1);
s1.insert(e2);
s2.insert(e2);
s2.insert(e3);

set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), s3.begin());

Solution

  • set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(),
                   std::inserter(s3, s3.begin()));
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    Example: http://ideone.com/B4Cc1

    By putting s3.begin() as the output iterator, you would mean that you want to overwrite the front region of the set with the set difference. Overwriting requires the size of set being larger than the result, which is obviously not true most of the time; even if the set is not empty, you can't use s3.begin() as output because the iterator is read-only (otherwise it would destroy the sorted order).

    OTOH, std::inserter(x, cit) means that, whenever this output iterator is assigned (*it = y), the insert method will be called (x.insert(cit, y)), which is what you really want: populate a set from empty.