Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In this non-compliant example, the IntSetLE type defines a set with less_equal specified as the ordering rule. Less than or equal is not a valid ordering rule because it violates the requirement to provide a "strict weak ordering" over the objects compared. In particular, this ordering rule fails to return false for equal values. As a result, the iterator pair returned by the equal_range() method is inverted and the subsequent loop fails to terminate.

Code Block
bgColor#FFcccc
langcpp
typedef set<int, less_equal<int > > IntSetLE;

IntSetLE::const_iterator sleIter;
IntSetLE sle;

sle.insert(5);
sle.insert(10);
sle.insert(20);

pair<IntSetLE::const_iterator, IntSetLE::const_iterator> psle;

psle = sle.equal_range(10);

for (sleIter = psle.first; sleIter != psle.second; ++sleIter){
    cout << "Set contains: " << *sleIter << endl;
}

...

Provide an ordering rule that defines a strict weak ordering.

Code Block
bgColor#ccccff
langcpp
typedef set<int, less<int> > IntSetLess;

IntSetLess::const_iterator islIter;
IntSetLess isl;

isl.insert(5);
isl.insert(10);
isl.insert(20);

pair<IntSetLess::const_iterator, IntSetLess::const_iterator> pisl;

pisl = isl.equal_range(10);

for (islIter = pisl.first; islIter \!= pisl.second; \++islIter) {
  cout << "Set contains: " << \*islIter << endl;
}

...

In this non-compliant example, the IntPtrSet type defines a set of int pointers using the default comparison operator as the ordering rule. Unfortunately the default comparison operator will compare the pointer address values, not the values of the ints referenced by the pointers. As a result, the integers will be ordered consistently, but their order will appear to be scrambled.

Code Block
bgColor#FFcccc
langcpp
typedef set<int*> IntPtrSet;

IntPtrSet::const_iterator sIter;
IntPtrSet s;

int i[3] = {10, 20, 5};
s.insert(&i[2]);
s.insert(&i[1]);
s.insert(&i[0]);

cout << "Set contains ";
for (sIter = s.begin(); sIter != s.end(); ++sIter) cout << **sIter << ' ';
cout << endl;

...

Wiki Markup
To store pointers in a proper order, you should use the {{DereferenceLess}} template, as described in 
\[[Meyers 01|AA. Bibliography#Meyers 01]\] Item 20:

Code Block
bgColor#ccccff
langcpp
struct DereferenceLess {
  template <typename PtrType>
  bool operator()(PtrType pl1, PtrType pl2) const {
    return *pl1 < *pl2;
  }
};

Now if we use this template when declaring the set:

Code Block
bgColor#ccccff
langcpp
typedef set<int*, DereferenceLess> IntPtrSet;

...