I get this problem while doing some experiment with set.
I use a structure with 2 integers as the key:
struct Key {
int k1;
int k2;
};
And use a class to build the ordering between keys:
struct keyComp {
bool operator () (const struct Key& lhs, const struct Key& rhs) const {
if (lhs.k1 < rhs.k1)
return true;
else if (lhs.k2 < rhs.k2)
return true;
else
return false;
}
};
But with this comparator, the set failed to find some existing keys. For example, in this program I store 9 keys in the set, from (0, 0) to (2, 2):
Key pos;
set <Key, keyComp> aset;
// insert elements from (0, 0) to (2, 2)
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
pos.k1 = i;
pos.k2 = j;
aset.insert (pos);
}
}
// now try to find each of them
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
pos.k1 = i;
pos.k2 = j;
set <Key, keyComp> :: iterator it = aset.find (pos);
if (it != aset.end ())
cout << "v "; // element found
else
cout << "! "; // not found
}
cout << endl;
}
// print the set
cout << "element in set : ";
for (set <Key, keyComp> :: iterator it = aset.begin (); it != aset.end (); it++) {
cout << "(" << it->k1 << ", " << it->k2 << ") ";
}
cout << endl;
I expect it would print 9 v‘s, which means all keys are found. But instead I got:
v v v
! ! v
! ! v
element in set : (0, 0) (1, 0) (2, 0) (0, 1) (1, 1) (2, 1) (0, 2) (1, 2) (2, 2)
Some keys can be found, but some can’t even they are in the set.
Also, if I change the comparator to:
struct keyComp {
bool operator () (const struct Key& lhs, const struct Key& rhs) const {
// combine the two keys for comparison
// say LARGE_NUMBER is a number bigger than all k2
return lhs.k1 * LARGE_NUMBER + lhs.k2 < rhs.k1 * LARGE_NUMBER + rhs.k2;
}
};
Then all keys are found.
Why is this happening? Is it because the original comparator failed to construct the order between keys?
Your comparator doesn’t provide a proper ordering, which means that the internals of
setwill do all manner of weird things (aka “undefined behaviour”) when trying to figure out where to insert or look-up things.You need something like this: