传递lambda函数作为参数时没有匹配的函数错误

ar2*_*015 8 c++ lambda type-conversion c++11 callable-object

我有一个数字列表.

我试图过滤列表,只保留正数.

我试图通过传递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;
}
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

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;});
                                                 ^
Run Code Online (Sandbox Code Playgroud)

leg*_*s2k 14

将功能更改keep

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

实例.

这适用于以下useful任何一个参数:

  • 拉姆达
  • std::function
  • 函子
  • 功能指针

文档:

lambda表达式构造一个未命名的prvalue临时对象,该对象具有唯一的非命名非联合非聚合类型,称为闭包类型.

这意味着具有相同代码的两个lambdas将生成两个不同的类型对象.

auto f1 = [](int) { return true; };
auto f2 = [](int) { return false; };
f2 = f1;                               // error: no viable '='
Run Code Online (Sandbox Code Playgroud)

但是,这两个都可以隐式转换为相应的std::function类型:

std::function<bool(int)> fn = f1;
fn = f2;
Run Code Online (Sandbox Code Playgroud)

但那么为什么它不适合你的情况呢?这是因为模板类型扣除.更改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
Run Code Online (Sandbox Code Playgroud)

将使您的示例编译而不在调用者站点进行任何强制转换.

但是,尝试匹配它将std::function<T>无法正常工作,因为模板类型扣除不考虑任何转换.模板参数推导查找精确类型匹配.在这个阶段,隐含的转换并不重要.您必须将其显式转换为匹配std::functionAtomic_alarm注释.就像Joseph在如何使用模板将lambda转换为std :: function中所述:

模板类型推导尝试将lambda函数的类型与std::function<T>在这种情况下它不能执行的类型相匹配- 这些类型不同.模板类型推导不考虑类型之间的转换.

在替代解决方案中,发生的事情是这样的:

auto f = [](int i) { return (i >= 0); }
Run Code Online (Sandbox Code Playgroud)

f这里的类型不是,std::function但推导出一些类似于Func上面模板参数的未命名类型.

如果您仍然希望这样做std::function,请参阅此答案,该答案使用其他模板间接方式.有关详细信息,请参阅此答案本文.

  • @ ar2015,lambda表达式有自己的类型,所以显式转换,或者使用模板.IDEone:http://ideone.com/r2gYTh (2认同)