It is a quirk of C++ that arbitrary pointers of the same type are not (necessarily) comparable with <, but are comparable with std::less
.
Unfortunately, the operator<
for std::pair
is defined in terms of operator<
on the components, not std::less
.
So, assuming that you want two pairs to fall in the same sort position if and only if they point to the same two objects, you need:
// "less than"
template<typename T>
bool lt(const T &lhs, const T &rhs) {
return std::less<T>()(lhs, rhs);
}
typedef std::pair<SomeClass*, SomeClass*> mypair;
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lt(lhs.first, rhs.first)
|| (!lt(rhs.first, lhs.first) && lt(lhs.second, rhs.second));
}
On pretty much any system you can name, this should compile to the same code as return lhs < rhs;
, but that is not formally correct. If the referands of the pointers are all subobjects of the same object (for instance if you have a huge array and all the pairs point to elements of that one array), then operator<
is OK for the pointers and hence OK for std::pair<pointer,pointer>
.
If you want to pairs to fall in the same sort position if and only if the objects they point to sort the same, then you'd add the extra dereference:
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lt(*lhs.first, *rhs.first)
|| (!lt(*rhs.first, *lhs.first) && lt(*lhs.second, *rhs.second));
}
and perhaps you'd also add checks for null pointers, if those are permitted. Of course if you know that SomeClass really is a class type, not a pointer type, then you don't need to use std::less
in the version above, just define operator<
for SomeClass and:
inline bool lessptr(const SomeClass *lhs, const SomeClass *rhs) {
if (lhs == 0) return rhs != 0;
if (rhs == 0) return false;
return *lhs < *rhs;
}
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lessptr(lhs.first, rhs.first)
|| (!lessptr(rhs.first, lhs.first) && lessptr(lhs.second, rhs.second));
}
You may or may not be able to optimise that a bit, since there are some repeated null checks performed in both the first and second calls to lessptr. If you care that much, see what the compiler does with it.