如何使用成员函数初始化`std :: function`?

时间:2014-05-30 19:22:07

标签: c++ c++11

我正在尝试学习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);

如何使这项工作成功,即如何将成员函数作为参数传递?

2 个答案:

答案 0 :(得分:9)

print_addfoo的非静态成员函数,这意味着它必须在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));

Live demo

答案 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)


<强>文档