C++ 将STL算法传递给另一个函数
我有一个用户定义类型的向量(Student)。我有两个几乎相同的函数,除了其中的一个函数调用 以下是两个功能:C++ 将STL算法传递给另一个函数,c++,c++11,stl,C++,C++11,Stl,我有一个用户定义类型的向量(Student)。我有两个几乎相同的函数,除了其中的一个函数调用 以下是两个功能: Student lowest_grade(const std::vector<Student> &all_students){ return *std::min_element(std::begin(all_students), std::end(all_students), [](const Student &a, const Studen
Student lowest_grade(const std::vector<Student> &all_students){
return *std::min_element(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
}
Student highest_grade(const std::vector<Student> &all_students){
return *std::max_element(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
}
学生最低分数(const std::vector&所有学生){
return*std::min_元素(std::begin(所有学生),std::end(所有学生),
[](康斯特学生与a、康斯特学生与b){
返回a.get_average()
这两个函数在我的使用中都正常工作,但似乎可以很容易地构造出更好的函数。我想创建一个函数,可以传入minu元素或max元素,比如:
template <typename func>
Student dispatch(const std::vector<Student> &all_students, func){
return *func(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
}
模板
学生派遣(const std::vector&all_学生,func){
return*func(标准::开始(所有学生),标准::结束(所有学生),
[](康斯特学生与a、康斯特学生与b){
返回a.get_average()
但我无法让它正常工作。我不知道该怎么做
编辑-这是我调用分派函数+错误消息的方式:
std::cout<<"lowest: "<< dispatch(all_students, std::max_element);
std::cout这样就可以了:
template <typename func>
Student dispatch(const std::vector<Student> &all_students, const func& fn){
return *fn(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
}
模板
学生派遣(const std::vector&all_学生,const func&fn){
返回*fn(标准::开始(所有学生),标准::结束(所有学生),
[](康斯特学生与a、康斯特学生与b){
返回a.get_average()
模板参数只是某种类型的东西
我建议要小心,永远不要使用空向量调用此方法,因为它在取消引用空迭代器时会引发异常。最好是:
template <typename func>
Student dispatch(const std::vector<Student> &all_students, const func& fn){
auto it = fn(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
if (it != all_students.end()) {
return *it;
}
// Some exception handling, because returning an instance of student is not possible.
}
模板
学生派遣(const std::vector&all_学生,const func&fn){
自动it=fn(标准::开始(所有学生),标准::结束(所有学生),
[](康斯特学生与a、康斯特学生与b){
返回a.get_average()
另一个建议是在使用数据之前对学生进行分类。然后,您还可以获得其他统计数据,如中位数
std::sort(all_students.begin(), all_students.end() [](const Student &a, const Student &b){return a.get_average() < b.get_average();});
std::sort(all_Student.begin(),all_Student.end()[](const Student&a,const Student&b){返回a.get_average()
最低的学生是第一要素,最高的学生是最后一要素。这也将防止您引发异常
你的电话还有一个问题。您需要呼叫dispatch,如:
dispatch(all_students, std::max_element<std::vector<Student>::const_iterator, std::function<bool(const Student &, const Student &)>>);
dispatch(所有学生,标准::最大元素);
STL没有演绎魔法,无法自行决定您想要的max\u元素
功能。因此您必须指定它。std::max_元素
是一个模板函数,编译器无法以这种方式推断所需的模板类型
您可以使用以下命令强制选择所需的原型:
// Your lambda as functor
struct CompAverage
{
bool operator () (const Student & a, const Student & b) const
{
return a.get_average() < b.get_average();
}
};
using Student_IT = std::vector<Student>::const_iterator;
Student dispatch(const std::vector<Student> &all_students,
Student_IT (*f)(Student_IT, Student_IT, CompAverage))
{
return *f(std::begin(all_students), std::end(all_students), CompAverage{});
}
int main()
{
std::vector<Student> v(42);
dispatch(v, &std::min_element);
dispatch(v, &std::max_element);
return 0;
}
//您的lambda作为函子
结构平均值
{
布尔运算符()(常量学生&a、常量学生&b)常量
{
返回a.get_average()
您的函数可以按如下方式编写:
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();});
}
另一种方法是始终在dispatch中调用min_元素
,但传入具有不同行为的比较器
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>()); // requires operator> for Student
在所有不同的选项中。我的首选方法是将算法包装到lambda中,然后将lambda传递给模板函数。当您将其包装到宏中时,它有很好的语法:
#define LIFT(...) \
([](auto&&... args) -> decltype(auto) { \
return __VA_ARGS__(std::forward<decltype(args)>(args)...); \
})
template <typename Func>
Student dispatch(const std::vector<Student> &all_students, Func func){
return *func(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
}
// ...
std::cout<<"lowest: "<< dispatch(all_students, LIFT(std::max_element));
定义提升(…)\
([](自动和…参数)->decltype(自动){\
返回uu VA_ARGS_uuu(标准::转发(ARGS)…)\
})
模板
学生派遣(const std::vector&all_学生,Func Func){
return*func(标准::开始(所有学生),标准::结束(所有学生),
[](康斯特学生与a、康斯特学生与b){
返回a.get_average() 你能详细说明一下它是如何失效的吗?特别是请展示如何使用分派
功能。如果同时计算最小值和最大值,请考虑。我应该更清楚,我意识到排序可能是最好的选择,但这只是学习C11的一个小演示程序。尽管我不喜欢定义,这是一个很好的魔法:)这看起来非常熟悉。使用,您还可以使用ordered_by(MFLIFT(get_average))
代替lambda。
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>);
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>()); // requires operator> for Student
auto minmax = std::minmax_element(std::begin(students), std::end(students));
#define LIFT(...) \
([](auto&&... args) -> decltype(auto) { \
return __VA_ARGS__(std::forward<decltype(args)>(args)...); \
})
template <typename Func>
Student dispatch(const std::vector<Student> &all_students, Func func){
return *func(std::begin(all_students), std::end(all_students),
[](const Student &a, const Student &b){
return a.get_average() < b.get_average();});
}
// ...
std::cout<<"lowest: "<< dispatch(all_students, LIFT(std::max_element));