C++:boost::bind的一些用法

来源:互联网 发布:one软件 编辑:程序博客网 时间:2024/06/15 15:41

没有对C++了解特别深入吧,还是对有些特性用法之类的不是很熟悉,阅读代码的时候还是碰到很多不明白。
下面是LZ读到的一句代码

boost::function<const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &> f = boost::bind(&MainLoop::onNewCloud, this, _1);

boost::bind的用法

目的
boost :: bind是标准函数std :: bind1st和std :: bind2nd的泛化。 它支持任意函数对象,函数,函数指针和成员函数指针,并且能够将任何参数绑定到特定值或将输入参数路由到任意位置。 bind对函数对象没有任何要求; 特别地,它不需要result_type,first_argument_type和second_argument_type标准typedef。

通过函数或者函数指针使用bind

int f(int a, int b){    return a+b;}int g(int a, int b, int c){    return a+b+c;}

bind(f, 1, 2)会产生一个零元函数,它不接受参数并且返回f(1, 2)。类似的,bind(g, 1, 2, 3)( )等同于g(1, 2, 3)。

可以选择性地绑定一些参数。 bind(f,_1,5)(x)等价于f(x,5); 这里_1是一个占位符参数,意思是“用第一个输入参数替换”。

为了比较,这里是与标准库原语相同的操作:

std::bind2nd(std::ptr_fun(f), 5)(x);

bind也包含std :: bind1st的功能:

std::bind1st(std::ptr_fun(f), 5)(x); //f(5, x)bind(f, 5, _1)(x);//f(5, x)

bind可以处理具有两个以上参数的函数,其参数替换机制更为通用:

bind(f, _2,_1)(x, y); //f(y, x)bind(g, _1, 9, _1)(x); //g(x, 9, x)bind(g, _3, _3, _3)(x, y, z); //g(z, z, z)bind(g, _1, _1, _1)(x, y, z); //g(x, x, x)

请注意,在最后一个示例中,由bind(g,_1,_1,_1)生成的函数对象不包含超出第一个参数的引用,但仍可以使用多个参数。 任何额外的参数被默认忽略,就像第一个和第二个参数在第三个例子中被忽略。

绑定的参数被返回的函数对象复制并保存在内部。 例如,在以下代码中:

int i = 5;bind(f, i, _1);

i的值的副本存储在函数对象中。 boost :: ref和boost :: cref可用于使函数对象存储对对象的引用,而不是副本:

int i = 5;bind(f, ref(i), _1);bind(f, cref(i), _1);

通过函数对象使用bind
绑定不限于功能; 它接受任意函数对象。 在一般情况下,必须明确指定生成的函数对象的operator()的返回类型(不使用typeof运算符,不能推断返回类型):

struct F{    int operator()(int a, int b){return a-b;}    bool operator()(long a, long b){return a == b;}};F f;int x = 104;bind<int>(f, _1, _1)(x); //f(x, x), i.e. zero

一些编译器遇到bind R(f,…)语法时遇到麻烦。 由于可移植性原因,支持表达上述的替代方法:

boost::bind(boost::type<int>(), f, _1, _1)(x);

但请注意,备用语法仅作为解决方法提供。 它不是界面的一部分。

当函数对象公开一个名为result_type的嵌套类型时,可以省略显式返回类型:

int x = 8;bind(std::less<int>(), _1, 9)(x); //x<9

[注意:省略返回类型的能力在所有编译器上都不可用]

默认情况下,bind将提供所提供的函数对象的副本。 boost :: ref和boost :: cref可用于使其存储对函数对象的引用,而不是副本。 当函数对象不可复制,复制昂贵或包含状态时,这可能很有用; 当然,在这种情况下,程序员期望确保功能对象在使用时不被销毁。

struct F2{    int s;    typedef void result_type;    void operator()(int x){ s+= x;}};F2 f2 = {0};int a[] = {1, 2, 3 };std::for_each(a, a+3, bind(ref(f2), _1));assert(f2.s == 6);

上面代码的目的是把a中的每个元素相加,求和结果保存到结构体f2.s中。

通过指向成员的指针使用bind

指向成员函数的指针和数据成员的指针不是函数对象,因为它们不支持operator()。 为方便起见,绑定接受成员指针作为其第一个参数,并且行为就好像已经使用boost :: mem_fn将成员指针转换为函数对象。 换句话说,表达为

bind(&X::f, args)

等价于

bind<R>(men_fn(&X::f), args)

其中R是X :: f(用于成员函数)的返回类型或成员的类型(对于数据成员)。

[注意:mem_fn创建能够接受指向对象的指针,引用或智能指针作为其第一个参数的函数对象; 有关其他信息,请参阅mem_fn文档。]

举例如下:

struct X{    bool f(int a);};X x;shared_ptr<X>p(new X);int i = 5;bind(&X::f, ref(x), _1)(i); //x.f(i)bind(&X::f, &x, _1)(i); //(&x)->f(i)bind(&X::f, x, _1)(i); //(internal copy of x).f(i)bind(&X::f, p, _1)(i); //(internal copy of p)->f(i)

最后两个例子很有趣,因为它们产生“自包含”功能对象。 bind(&X :: f,x,_1)存储x的副本。 bind(&X :: f,p,_1)存储p的副本,由于p是一个boost :: shared_ptr,函数对象保留对其X实例的引用,并且即使p超出范围也将保持有效, 是reset()。

对于函数组合使用嵌套binds(感觉这个翻译好奇怪!)
传递给绑定的一些参数可能是嵌套绑定表达式本身:

bind(f, bind(g, _1))(x); //f(g(x))

内部绑定表达式在调用函数对象之前以非特定顺序进行外部绑定之前的计算; 当外部绑定被评估时,评估结果将被替换为它们的位置。 在上面的例子中,当使用参数列表(x)调用函数对象时,首先评估bind(g,_1)(x),得到g(x),然后bind(f,g(x)) x),得到最终结果f(g(x))。

绑定的这个特征可以用来执行功能组合。 有关示例演示如何使用bind实现与Boost.Compose类似的功能的示例,请参见bind_as_compose.cpp。

请注意,第一个参数 - 绑定函数对象 - 不被评估,即使它是由bind或占位符参数生成的函数对象,因此下面的示例不能按预期方式工作:

typedef void (*pf)(int);std::vector<pf> v;std::for_each(v.begin(), v.end(), bind(_1, 5));

可以通过将其第一个参数作为函数对象应用到其参数列表的其余部分的帮助函数对象apply来实现所需的效果。 为方便起见,apply.hpp头文件中提供了apply的实现。 以前的例子的修改版本如下所示:

typedef void(*pf)(int)std::vector<pf> v;std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));

虽然第一个参数是,默认情况下不进行评估,但所有其他参数都是。 有时候,有必要在第一个之后评估参数,即使它们是嵌套的绑定子表达式。 这可以通过另一个函数对象的帮助来实现,保护,掩饰类型,以便绑定不能识别和评估它。 被调用时,保护简单地将参数列表转发到其他函数对象。

头文件protect.hpp包含一个保护的实现。 为了保护绑定函数对象免于评估,请使用protect(bind(f,…))。

重载操作符(new in Boost1.33)
为方便起见,通过绑定重载逻辑非运算符产生的函数对象! 和关系和逻辑运算符==,!=,<,<=,>,> =,&&,||。

!bind(f,…)等价于bind(logical_not(),bind(f,…)),其中logical_not是一个函数对象,它接受一个参数x并返回!x。

bind(f,…)op x,其中op是关系或逻辑运算符,相当于bind(relation(),bind(f,…),x),其中,关系是一个函数对象,需要两个 参数a和b并返回一个操作b。

这在实践中意味着你可以方便地否定绑定的结果:

std::remove_if(first, last, !bind(&X::visible, _1)); //remove invisible objects

并将绑定的结果与值进行比较:

std::find_if(first, last, bind(&X::name, _1) == "Peter");std::find_if(first, last, bind(&X::name, _1) == "Peter" || bind(&X::name, _1) == "Paul");

针对占位符:

bind(&X::name, _1) == _2

或者针对另外一个占位符:

std::sort(first, last, bind(&X::name, _1)< bind(&X::name, _2)); //sort by name

参考地址:
http://www.boost.org/doc/libs/1_65_1/libs/bind/doc/html/bind.html#bind.purpose.using_bind_with_functions_and_fu

原创粉丝点击