Причуда C ++ заключается в том, что произвольные указатели одного и того же типа (не обязательно) сравнимы с <, но сравнимы с <code>std::less.
К сожалению, operator<
для std::pair
определяется как operator<
для компонентов, а не std::less
.
Итак, предполагая, что вы хотите, чтобы две пары попали в одну и ту же позицию сортировки, если и только если они указывают на одни и те же два объекта, вы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));
}
Почти во всех системах, которые вы можете назвать, это должно компилироваться с тем же кодом, что и return lhs < rhs;
, но это не является формально правильным.Если ссылки всех указателей являются подобъектами одного и того же объекта (например, если у вас огромный массив, и все пары указывают на элементы этого одного массива), то operator<
в порядке для указателей и, следовательно, в порядке для std::pair<pointer,pointer>
.
Если вы хотите, чтобы пары попадали в одну и ту же позицию сортировки, если и только если объекты, на которые они указывают, сортируют одинаково, вы добавили бы разыменование:
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lt(*lhs.first, *rhs.first)
|| (!lt(*rhs.first, *lhs.first) && lt(*lhs.second, *rhs.second));
}
и, возможно, вы также добавите проверки на нулевые указатели, если они разрешены.Конечно, если вы знаете, что SomeClass действительно является типом класса, а не указателем, вам не нужно использовать std::less
в вышеприведенной версии, просто определите operator<
для SomeClass и:
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));
}
Вы можете или не можете оптимизировать этот бит, так как есть несколько повторных нулевых проверок, выполненных как при первом, так и во втором обращении к lessptr.Если вам так важно, посмотрите, что с ним делает компилятор.