我正在尝试学习std::function
,这是我的代码:
#include <iostream>
#include <functional>
struct Foo {
void print_add(int i){
std::cout << i << '\n';
}
};
typedef std::function<void(int)> fp;
void test(fp my_func)
{
my_func(5);
}
int main(){
Foo foo;
test(foo.print_add);
return 0;
}
编译错误:
error: cannot convert 'Foo::print_add' from type 'void (Foo::)(int)' to type 'fp {aka std::function<void(int)>}'
test(foo.print_add);
如何使这项工作成功,即如何将成员函数作为参数传递?
答案 0 :(得分:9)
print_add
是foo
的非静态成员函数,这意味着它必须在Foo
的实例上调用;因此它有一个隐含的第一个参数,this
指针。
使用捕获foo
实例的lambda并在其上调用print_add
。
Foo foo;
test([&foo](int i){ foo.print_add(i); });
另一种选择是使用std::bind
绑定foo
实例:
test(std::bind(&Foo::print_add, &foo, std::placeholders::_1));
答案 1 :(得分:3)
问题
您无法直接将属于Foo
类型的成员函数指针绑定到std::function<void(int)>
,特别是因为调用非静态成员函数需要Foo
类型的实例。
Foo obj; obj.member_function (); // can't call `member_function` without `obj`
注意:您可以将&Foo::print_add
绑定到std::function<void(Foo&, int)> x;
,并将其称为x(instance_of_Foo, arg);
。
注意:也可以将其绑定到std::function<void(Foo*, int>
,这需要Foo*
而不是左值类型Foo
。
解决方案
相反,您可以使用std::bind
绑定 Foo
的实例到相关的成员函数,例如下面的示例:
int main(){
Foo foo;
test (std::bind (&Foo::print_add, foo, std::placeholders::_1));
return 0;
}
上面我们将名为Foo
的{{1}}实例绑定到成员函数指针 foo
。
&Foo::print_add
的使用告诉std::placeholders::_1
我们希望生成一个可以使用一(1)个参数调用的函数对象。
使用上面的代码片段,您将拥有您当前要求的行为; std::bind
等同于调用my_func(5)
。
<强>文档强>