我有一个数字列表。
我正在尝试过滤列表并只保留正数。
我试图通过传递一个 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;});
^
最佳答案
改变函数keep
到
template<typename T, typename Func>
std::vector<T> keep(const std::vector<T> &original,
Func useful)
{
// code as usual
}
这适用于 useful
的参数是以下任何一个:
- lambda
-
std::function
- functor
- 函数指针
来自 the documentation :
The lambda expression constructs an unnamed prvalue temporary object of unique unnamed non-union non-aggregate type, known as closure type.
这意味着具有相同代码的两个 lambda 将生成两个不同类型的对象。
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;
但是为什么它在您的情况下不起作用?这是因为模板类型推导。改变 keep
到
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了解相关详情。
关于c++ - 将 lambda 函数作为参数传递时没有匹配函数错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32840369/