2015-09-29 46 views
6

我有一个数字列表。将lambda函数作为参数传递时没有匹配的函数错误

我想过滤列表,只保留正数。

我想通过传递一个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;}); 
               ^
+1

您可以使用标准库算法[std :: copy_if](http://en.cppreference.com/w/cpp/algorithm/copy)更轻松地完成此操作:http://coliru.stacked- crooked.com/a/99cdc73f48d19ba7 – Andrew

+0

错误消息中的代码与您的代码不匹配。 – molbdnilo

+0

你用什么编译器? –

回答

10

改变功能keep

template<typename T, typename Func> 
std::vector<T> keep(const std::vector<T> &original, 
        Func useful) 
{ 
    // code as usual 
} 

Live example

这与争论工程useful是其中任何一项:

  • 拉姆达
  • std::function
  • functor
  • 函数指针

the documentation

lambda表达式构造一个未命名的非聚合非聚合类型的非名称的临时对象,称为闭包类型。

这意味着两个具有相同代码的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,作为原子_报警评论。像约瑟夫说,在How to convert a lambda to an std::function using templates

模板类型推演试图您的lambda表达式类型相匹配的std::function<T>它只是不能在这种情况下做的 - 这些类型是不一样的。模板类型扣除不考虑类型之间的转换。

而在另一种解决方案发生的事情是这样的:

auto f = [](int i) { return (i >= 0); } 

类型的f这里就不std::function但一些不愿透露姓名的类型推断像它会为上面的模板参数Func

如果您仍然想要这样做std::function的方式,请参阅this answer它与其他模板间接使用它。有关详细信息,请参阅this answerthis post

+0

谢谢。仍然我想知道我的代码有什么问题?我在哪里犯了一个错误? – ar2015

+2

@ ar2015,lambda表达式有它自己的类型,所以明确强制转换或使用模板。 IDEone:http://ideone.com/r2gYTh –

+0

@ ar2015详细的原因现在在更新的答案。 – legends2k

相关问题