boost::bind 是标准函数std::bind1st和std::bind2nd的泛型。它支持函数、函数对象、函
数指针和成员函数指针。它可以绑定任何参数到一个具体的值或者函数到预定义好的位置。
-----------------在函数和函数指针中使用-----------------
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); // = f(x, 5);
当然也可以绑定第一个参数。例如 std::bind1st(Std::ptr_fun(f), 5)(x); // = f(5, x);
bind还可以处理多于两个参数的函数
bind(f, _1, _2, _3)(x, y, z);
参数的传递方式:值传递和引用传递
int i = 5;
bind(f, i, _1);
i的值拷贝会存储在函数对象中。但是如果使用boost::ref或者boost::cref就可以让函数对
象存储一个对象的而引用或者常引用而不是拷贝。
-----------------在函数对象中使用-----------------
bind的使用不仅限于函数,它还支持函数对象。
通常情况下(在result_type没有被指定的情况下),operator()必须显示的设置返回值类型。
struct F
{
int operator()(int a, int b) { return a - b; }
bool operator()(long a, long b) { return a == b; }
};
F f;
int x = 1;
bind<int>(f, _1, _1)(x);
注意bind后面加的<int>,这里就表示函数对象的返回值类型。如果有些编译器不支持这种方
式,可以这样来替代。
bind(boost::type<int>(), f, _1, _1)(x);但这只是提供了一种变通方案,并不是接口的一
部分。
在特殊情况下,也就是result_type被指定的情况下,这个显示的返回类型就可以省去。例如
下面的bind后面就没有返回值类型。
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 );
-----------------在成员函数中使用-----------------
成员函数和成员变量的指针不是函数对象,因为它们不支持operator()。为了方便考虑,
bind接收成员指针作为它第一个参数,行为就像boost:mem_fn用来把成员指针转换成一个函
数对象。也就是说表达式bind(&X::f, args)
就等于bind<R>(mem_fn(&X::f),args) // R表示X::f的返回类型或者数据类型。
而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()都将可用。
-----------------使用嵌套bind组成函数-----------------
bind(f, bind(g, _1)) (x) // f(g(x))
内层的bind表达式会比外层的bind先被处理;处理的结果会提交到当外部bind被处理的时候的
位置。在这里bind(g, _1)(x)会被最先处理,产生g(x),并且绑定bind(f,g(X))(X)生成最后
的f(g(X))。
当函数对象的是由参数本身或是占位符指定时,以下将不能得到预期的效果
typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(_1, 5));
在此我们可以通过使用apply来指定它的第一个参数,作为函数对象。apply在头文件
boost/bind/apply.hpp中定义。所以我们可以这样修改代码。
std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));
BOOST::bind 如何使用
最新推荐文章于 2022-04-29 08:18:42 发布