Your function can be written as you want:
template<typename Func> Student dispatch(const std::vector<Student> &all_students, Func func) { assert(!all_students.empty()); return *func(std::begin(all_students), std::end(all_students), [](const Student &a, const Student &b){ return a.get_average() < b.get_average();}); }
And is called as
dispatch(students, std::min_element<decltype(students)::const_iterator, bool(*)(const Student&, const Student&)>); dispatch(students, std::max_element<decltype(students)::const_iterator, bool(*)(const Student&, const Student&)>);
You can slightly reduce the amount of text if you implement operator< for Student . This will allow you to omit the template argument for the comparator.
template<typename Func> Student dispatch(const std::vector<Student> &all_students, Func func) { assert(!all_students.empty()); return *func(std::begin(all_students), std::end(all_students)); } dispatch(students, std::min_element<decltype(students)::const_iterator>); dispatch(students, std::max_element<decltype(students)::const_iterator>);
Another way to do this is to always call min_element in dispatch, but pass in comparators with different behaviors.
template<typename Comparator> Student dispatch(const std::vector<Student> &all_students, Comparator comp) { assert(!all_students.empty()); return *std::min_element(std::begin(all_students), std::end(all_students), comp); } dispatch(students, std::less<Student>()); dispatch(students, std::greater<Student>());
Finally, if you always get both the lowest and highest grades, the standard library offers std::minmax_element , which will be retrieved both in one call.
auto minmax = std::minmax_element(std::begin(students), std::end(students));
Live demonstration of all the various parameters.