Comparator
rlbond does not prevent the insertion of elements that compare the same way. This seems to be hard to prove in the comments, given the character limit, as rlbond seems to believe that std :: set ensures that it will never contain two elements with !compare(a,b) && !compare(b,a) for its comparator. However, the rlbond comparator does not determine the strict order and, therefore, is not a valid parameter for std :: set.
#include <set> #include <iostream> #include <iterator> #include <algorithm> struct BrokenOrder { int order; int equality; public: BrokenOrder(int o, int e) : order(o), equality(e) {} bool operator<(const BrokenOrder &rhs) const { return order < rhs.order; } bool operator==(const BrokenOrder &rhs) const { return equality == rhs.equality; } }; std::ostream &operator<<(std::ostream &stream, const BrokenOrder &b) { return stream << b.equality; } // rlbond magic comparator struct LessThan : public std::binary_function<BrokenOrder, BrokenOrder, bool> { bool operator()(const BrokenOrder& lhs, const BrokenOrder& rhs) const { return !(lhs == rhs) && (lhs < rhs); } }; int main() { std::set<BrokenOrder,LessThan> s; for (int i = 0; i < 5; ++i) { s.insert(BrokenOrder(i,i)); } for (int i = 0; i < 5; ++i) { s.insert(BrokenOrder(10-i,i)); } std::copy(s.begin(), s.end(), std::ostream_iterator<BrokenOrder>(std::cout, "\n")); }
Output:
0 1 2 3 4 3 2 1 0
Duplicates The magic comparator failed. Different elements in the set have the same value of equality and, therefore, compare them with operator== , because when inserting the set never compared the new element with its duplicate. The only duplicate that was excluded was 4 because the two 4 had sort orders 4 and 6. This put them close enough to each other in the set to compare with each other.
From the C ++ standard: 25.3: 3 "For the algorithms to work correctly, comp must cause strict weak ordering by values."
25.3: 4 "... the requirements are that comp and equiv are both transitive relationships:
comp(a,b) && comp(b,c) implies comp(a,c)"
Now consider the elements a = BrokenOrder(1,1) , b = BrokenOrder(2,2) and c = BrokenOrder(9,1) and comp , of course, equal to the magic comparator. Then:
comp(a,b) true, since 1! = 2 (equality) and 1 <2 (order)comp(b,c) true since 2! = 1 (equality) and 2 <9 (order)comp(a,c) is false since 1 == 1 (equality)