代码之家  ›  专栏  ›  技术社区  ›  canellas

STD::绑定到STD::具有返回值的函数[复制]

  •  0
  • canellas  · 技术社区  · 6 年前

    我有一张号码表。

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

    我试图通过传递一个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;});
                                                     ^
    
    0 回复  |  直到 6 年前
        1
  •  14
  •   Community Mohan Dere    8 年前

    更改功能 keep

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

    Live example .

    这与 useful 作为其中之一:

    the documentation :

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

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

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

    但是,这两个都可以隐式地转换为 STD::功能 类型:

    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::函数 作为 原子报警 评论。就像约瑟夫说的 How to convert a lambda to an std::function using templates :

    模板类型推断尝试将lambda函数的类型与 STD::功能& LT&T; 但在这种情况下它不能这么做-这些类型不一样。模板类型推断不考虑类型之间的转换。

    而在另一种解决方案中,会发生如下情况:

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

    类型 f 这里不是 STD::功能 但是一些未命名的类型会像模板参数那样导出 Func 上面。

    如果你还想这么做 std::函数 路,见 this answer 它通过一个附加的模板间接寻址来实现。见 this answer this post 相关细节。