让我们关注这个例子:
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实现它。
答案 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
这样就可以将参数转换为参数类型。
此外,函数的类型应匹配。即它应该接受字符串引用。