我试图过滤列表,只保留正数.
我试图通过传递lambda作为参数来做到这一点.
#include <vector> #include <algorithm> #include <functional> template<typename T> std::vector<T> keep( const std::vector<T> &original,std::function<bool(const T&)> useful) { std::vector<T> out; for(T item:original) { if(useful(item)) out.push_back(item); } return out; } int main() { std::vector<int> a={4,6,2,-5,3,-8,13,-11,27}; a=keep(a,[](const int& x)->bool{return x>0;}); for(int y:a) { std::cout<<y<<std::endl; } return 0; }
这是错误消息:
error: no matching function for call to ‘keep(std::vector<int>&,main()::<lambda(const int&)>)’ a=keep(a,[](const int& x)->bool{return x>0;}); ^
解决方法
template<typename T,typename Func> std::vector<T> keep(const std::vector<T> &original,Func useful) { // code as usual }
这适用于以下任何一个有用的参数:
> lambda
> std :: function
> functor
>函数指针
The lambda expression constructs an unnamed prvalue temporary object of unique unnamed non-union non-aggregate type,known as closure type.
这意味着具有相同代码的两个lambdas将生成两个不同的类型对象.
auto f1 = [](int) { return true; }; auto f2 = [](int) { return false; }; f2 = f1; // error: no viable '='
但是,这两个都可以隐式转换为相应的std :: function类型:
std::function<bool(int)> fn = f1; fn = f2;
但那么为什么它不适合你的情况呢?这是因为模板类型扣除.改变保持
template<typename T> std::vector<T> keep(const std::vector<T> &original,std::function<bool(const int &)> useful) // no type deduction for std::function's template,explicitly mentioned
但是,尝试将其与std :: function< T>匹配因为模板类型扣除不考虑任何转换,所以不起作用.模板参数推导查找精确类型匹配.在这个阶段,隐含的转换并不重要.您必须将它显式地转换为匹配的std :: function作为Atomic_alarm注释.就像约瑟夫在How to convert a lambda to an std::function using templates所说:
Template type deduction tries to match the type of your lambda function to the
std::function<T>
which it just can’t do in this case – these types are not the same. Template type deduction doesn’t consider conversions between types.
在替代解决方案中,发生的事情是这样的:
auto f = [](int i) { return (i >= 0); }
这里的f类型不是std :: function,而是推导出一些未命名的类型,就像上面的模板参数Func一样.
如果您仍然希望以std :: function方式执行此操作,请参阅this answer,它使用其他模板间接方式执行此操作.有关详细信息,请参见this answer和this post.