您的位置:首页 > 其它

【boost学习】之boost::bind

2014-10-22 01:02 387 查看
Purpose(目的)

原来文档中的purpose完全就是教程了,事实上,bind主要用于改造函数,比如,一个地方需要一个无参的函数,你只有一个以int为参数的函数,并且你知道此时int一直为1就可以了,你怎么办?传统方法,直接实现一个函数,然后以1调用以前的那个int为参数的函数。如下:

void  Fun1(int  i) {
printf(" %d /n " , i);
}

void  FunWeNeed() {
Fun1(1 );
}

int  main()
{
FunWeNeed();

return  0 ;
};


当然,这个例子太扯了,我们只需要直接用Fun1(1)调用就可以了,但是bind的目的就是如此,只不过现实中因为各种各样的原因,你的确需要改造函数。再比如下面的情况,你有一个原来写好的函数,接受一个以无参函数为参数,那么,你的Fun1就没有办法派上用场了,那么,传统上,怎么办?如下:

typedef   void  FunWeNeed_t(void );

void  CallFun( FunWeNeed_t f) {
f();
}

void  Fun1(int  i) {
printf(" %d /n " , i);
}

void  FunWeNeed() {
Fun1(1 );
}

int  main()
{

//  CallFun(Fun1);          // this line can't compile
CallFun(FunWeNeed);

return  0 ;
};


Ok,你不得不写新的函数以满足需求,因为你没有简单的办法改变一个函数的参数。

给个bind的解决方案吧。

#include <boost/bind.hpp>
#include <boost/function.hpp>

void  CallFun( boost::function<void (void )> f) {
f();
}

void  Fun1(int  i) {
printf(" %d /n " , i);
}

void  FunWeNeed() {
Fun1(1 );
}

int  main()
{

CallFun(boost::bind(Fun1, 1 ));         // this line can't compile
CallFun(FunWeNeed);

return  0 ;
};


需要注意的是,此时不能再使用函数指针了,bind的天生合作伙伴是function,而function是支持函数指针的(如上例所示) 。目的将的很多了,下面看看用法吧(不是什么问题)。

普通函数

最有意思的是,你甚至能用bind来扩充原有函数的参数,见下例:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using  namespace  std;
using  namespace  boost;

void  f(int  a, int  b)
{
cout <<"Argument 1 is "  <<a <<endl;
}

void  g(int  a, int  b, int  c)
{
cout <<"sum is "  <<a+b+c <<endl;
cout <<"arg 1: "  <<a <<endl;
cout <<"arg 2: "  <<b <<endl;
cout <<"arg 3: "  <<c <<endl;
cout <<"---------------------------"  <<endl;
}

int  main()
{

function<void (int ,int )>  f1= bind(f, _2, _1);                 // 调整参数1,2的位置
f1(1 , 2 );

function<void (int )> sum1 = bind(g, _1, _1, _1);        // 3个参数变1个
sum1(10 );

function<void (int , int )> sum2 = bind(g, _2, _2, _2);       // 3个参数变2个,仅用一个
sum2(10 , 20 );

function<void (int , int , int )> sum3 = bind(g, _3, _3, _3);      // 3个参数还是3个,但是仅用1个
sum3(10 , 20 , 30 );

function<void (int , int , int , int )> sum4 = bind(g, _4, _4, _4);     // 3个参数变4个,但是仅用1个
sum4(10 , 20 , 30 , 40 );

return  0 ;
};


输出结果:

Argument 1 is 2

sum is 30

arg 1: 10

arg 2: 10

arg 3: 10

---------------------------

sum is 60

arg 1: 20

arg 2: 20

arg 3: 20

---------------------------

sum is 90

arg 1: 30

arg 2: 30

arg 3: 30

---------------------------

sum is 120

arg 1: 40

arg 2: 40

arg 3: 40

---------------------------

函数对象

注意用法中很重要的一条:通常情况下,生成的函数对象的 operator() 的返回类型必须显式指定(没有 typeof 操作符,返回类型无法推导)。(来自Boost文档)

#include <boost/bind.hpp>
#include <boost/function.hpp>
using  namespace  std;
using  namespace  boost;

struct  F
{
int  operator ()(int  a, int  b) { return  a - b; }
bool  operator ()(long  a, long  b) { return  a == b; }
};

int  main()
{
F f;

int  x = 104 ;

function< int (int ) > fun1 = bind<int >(f, _1, _1);      // f(x, x), i.e. zero

cout <<fun1(1 );

function< bool (long ) > fun2 = bind<bool >(f, _1, _1);       // f(x, x), i.e. zero

cout <<fun2(1 );

return  0 ;
};


其他的也就很简单了。

成员指针

例子来源于boost文档。

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/smart_ptr.hpp>
using  namespace  std;
using  namespace  boost;

struct  X
{
void  f(int  a) {
cout <<a <<endl;
}
};

int  main()
{
X x;

shared_ptr<X> p(new  X);

int  i = 1 ;

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)

return  0 ;
}


可见bind的强大,支持自己拷贝需要的对象,支持引用,甚至,支持智能指针。

最后一个例子,结合标准库容器及算法的例子,这才是展示bind的强大的地方。

还是来自于boost文档。

class  image;
class  animation
{
public :

void  advance(int  ms);
bool  inactive() const ;
void  render(image & target) const ;
};

std::vector<animation> anims;

template <class  C, class  P> void  erase_if(C & c, P pred)
{
c.erase(std::remove_if(c.begin(), c.end(), pred), c.end());
}

void  update(int  ms)
{
std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms));
erase_if(anims, boost::mem_fn(&animation::inactive));
}

void  render(image & target)
{
std::for_each(anims.begin(), anims.end(), boost::bind(&animation::render, _1, boost::ref(target)));
}


例子展示了erase_if,for_each算法中使用bind的方法。

【转自:http://blog.csdn.net/vagrxie/article/details/5509454】

个人总结一下:

(1)bind构造普通函数

(2)bind函数调整参数

(3)bind函数对象(表明返回类型)

(4)bind类的成员函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: