我不能将lambda作为std :: function传递

时间:2016-03-16 08:46:09

标签: c++ c++11 lambda

让我们关注这个例子:

template<typename T>
class C{
    public:
    void func(std::vector<T>& vec, std::function<T( const std::string)>& f){
        //Do Something
    }
};

现在,我正在努力:

std::vector<int> vec;
auto lambda = [](const std::string& s) { return std::stoi(s); };
C<int> c;
c.func(vec, lambda);

它会导致错误:

no matching function for call to ‘C<int>::func(std::vector<int, std::allocator<int> >&, main()::<lambda(const string&)>&)’
     ref.parse(vec, lambda);

请解释一下我还不行,以及如何使用std :: bind实现它。

2 个答案:

答案 0 :(得分:25)

这是因为lambda函数不是std::function<...>

的类型
auto lambda = [](const std::string& s) { return std::stoi(s); };

不是std::function<int(const std::string&)>,而是未指定的可分配给std::function的内容。现在,当您调用方法时,编译器会抱怨类型不匹配,因为转换意味着创建一个不能绑定到非const引用的临时类。

这也不是特定于lambda函数,因为传递普通函数时会发生错误。这不会起作用:

int f(std::string const&) {return 0;}

int main()
{
    std::vector<int> vec;
    C<int> c;
    c.func(vec, f);
}

您可以将lambda指定为std::function

std::function<int(const std::string&)> lambda = [](const std::string& s) { return std::stoi(s); };

,更改您的成员函数以通过值或const-reference获取函数或将函数参数设置为模板类型。如果传递lambda或普通函数指针,这会稍微有效,但我个人喜欢签名中富有表现力的std::function类型。

template<typename T>
class C{
    public:
    void func(std::vector<T>& vec, std::function<T( const std::string)> f){
        //Do Something
    }

    // or
    void func(std::vector<T>& vec, std::function<T( const std::string)> const& f){
        //Do Something
    }

    // or
    template<typename F> func(std::vector<T>& vec, F f){
        //Do Something
    }
};

答案 1 :(得分:16)

这是因为参数(std::function)是参考。它应该是:

void func(std::vector<T>& vec, std::function<T(const std::string&)> f)
                                                                ^  ^
                                                                   |
                                                                   f not a reference

这样就可以将参数转换为参数类型。

此外,函数的类型应匹配。即它应该接受字符串引用。