Вы можете определить служебный класс
template <class Fct> class compare_on {
public:
compare_on(Fct&& get) : get(std::forward<Fct>(get)) {}
template <class T> bool operator()(const T& lhs, const T& rhs)
{
return get(lhs) < get(rhs);
}
private:
Fct get;
};
и затем передайте его std::sort
, как вы его изобразили (используя вычет аргумента шаблона класса C ++ 17)
std::sort(students.begin(), students.end(),
compare_on([](const student& s){ return s.id; }));
Начиная с C ++ 17, @Justin указал в комментариях, что фактическое сравнение может быть улучшено (с #include <functional>
) таким образом, что
return std::invoke(get, lhs) < std::invoke(get, rhs);
, которая позволяет создавать экземпляры со ссылками на элементы данных:
std::sort(students.begin(), students.end(), compare_on(&student::id));
При связывании с C ++ 11 забудьте о std::invoke
и перейдите к явной реализации compare_on
. Последний не подходит для лямбд, поэтому обычный вывод аргументов make_*
helper:
template <class Fct> auto make_compare_on(Fct&& get)
-> decltype(compare_on<Fct>(std::forward<Fct>(get)))
{
return compare_on<Fct>(std::forward<Fct>(get));
}
Обратите внимание, что вы можете удалить конечный тип возврата в C ++ 14.
Как последнее замечание, здесь следует улучшить наименование: compare_on
вводит в заблуждение, поскольку оно скрывает, что на самом деле делает объект функции - сравнение с помощью operator <
. Может быть, compare_less_then
или что-то подобное будет лучше, или добавление другого параметра шаблона, который может быть указан в качестве одного из стандартных предикатов (std::less
и т. Д.).