std::set stores its values in a sorted binary tree, so it needs to know how to compare the values it holds. By default it uses std::less as a comparison function, which for un-specialized user defined types tries to call operator<. So, the easiest way to tell the set how to compare your objects is to define an operator< for your class:
template <class T, class S> class Property { public: pair<T,S> p; Property(T t, S s) { p = make_pair(t,s);} bool operator<(const Property<T,S>& rhs) const { return p < rhs.p; } };
However, there are also other ways of telling std::set how to compare your type. One is to specialize the std::less template for your class:
namespace std { template<typename T,typename S> struct less<Property<T, S> > { bool operator()(const Property<T, S>& lhs, const Property<T,S>& rhs) const { return lhs.p < rhs.p; } }; }
Another is to replace the default comparison type with a function with the correct signature, or a class that has an operator() defined with the correct signature. This is where things start to get ugly.
// Comparison function template<typename T, typename S> bool property_less_function(const Property<T,S>& lhs, const Property<T,S>& rhs) { return lhs.p < rhs.p; } // Comparison functor template<typename T, typename S> struct PropertyLess { bool operator()(const Property<T,S>& lhs, const Property<T,S>& rhs) const { return lhs.p < rhs.p; } }; int main() { // Set using comparison function. // Have to pass the function pointer in the constructor so it knows // which function to call. The syntax could be cleaned up with some // typedefs. std::set<Property<std::string, std::string>, bool(*)(const Property<std::string, std::string>&, const Property<std::string, std::string>&)> set1(&property_less_function<std::string, std::string>); // Set using comparison functor. Don't have to pass a value for the functor // because it will be default constructed. std::set<Property<std::string, std::string>, PropertyLess<std::string, std::string> > set2; }
Keep in mind that whatever less-than function you use, that function must define a strict weak ordering for your type.
std::unordered_setif you don't care about the ordering, which you don't seem to here, judging by the error you get, which I've magically deciphered from compiling this in my brain.std::unordered_setsince you have to provide a hash and equality operator.operator <(const Property&), the standardstd::sethas no way of determining identity of an element (which, btw, is done with(!(left < right) && !(right < left)), so make sure your order is consistent). Thestd::pair<>template defines the most commonly used order comparator already, so unless you have a specific reason not to, you could well easily solve your issue by simply throwing outPropertyas a formal definition and instead just usingtypedef std::pair<string,string> Property;I'm guessing, however, you need case-insensitive label comparison.