c++ set operations

Started by
9 comments, last by Storyyeller 12 years, 5 months ago
What is the simplest way to do intersections, unions, etc. of stl sets? As far as I can tell, there is no built in way to do this.

I tried defining my own operators, but it doesn't even work. And this is a needlessly tedious and error prone, and probably inefficient method anyway.

[source lang='cpp']
#include <algorithm>
template <typename T>
inline void operator &= (std::set<T>& a, const std::set<T>& b){
    std::set<T> c;
    std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), c.begin());
    a.swap(c);
}
[/source]
I trust exceptions about as far as I can throw them.
Advertisement
I don't understand what the problem with using std::set_intersection to find the intersection of two sets is. Is it too obfuscated a name?

Stephen M. Webb
Professional Free Software Developer

Well for one thing, the code I posted doesn't compile, and for another thing, I'd prefer to not have to write all those wrapper functions myself. Why isn't there any built in method for doing set intersections?
I trust exceptions about as far as I can throw them.
You need a writable iterator for set_intersection()'s output. Ex:

std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(c, c.begin()));
So is this really the best way to do set intersections?

template <typename T>
inline void operator &= (std::set<T>& a, const std::set<T>& b){
decltype(a) c;
std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(c, c.end()));
a.swap(c);
}

template <typename T>
inline void operator |= (std::set<T>& a, const std::set<T>& b){
decltype(a) c;
std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(c, c.end()));
a.swap(c);
}
I trust exceptions about as far as I can throw them.
Union is probably more efficiently performed by just a.insert(b.begin(), b.end()).
What about operators which create a new set? Should I return it by value or a move reference? I suppose RVO means it doesn't really matter.

template <typename T>
inline std::set<T> operator - (const std::set<T>& a, const std::set<T>& b){
std::set<T> c;
std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(c, c.end()));
return c;
}
I trust exceptions about as far as I can throw them.
Just return the set. If RVO doesn't kick in move semantics will eliminate most of the overhead anyway.

What about operators which create a new set? Should I return it by value or a move reference? I suppose RVO means it doesn't really matter.

template <typename T>
inline std::set<T> operator - (const std::set<T>& a, const std::set<T>& b){
std::set<T> c;
std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(c, c.end()));
return c;
}




If you create the set in the function and return it you have no other option then return by value, the set will be gone otherwise when you come to use it later on.Plus you will get a compiler warning stating that you are returing a local variable that can cause sideeffects.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

You could return an auto_ptr to the new set, that would take care of deleting it once you'd finished with it.

This topic is closed to new replies.

Advertisement