bind是一種非常神奇的存在,它不是一個單獨的類或者函數,依據綁定的參數的個數和要綁定的調用對象的類型,總共有數十種不同的形式,編譯器會根據具體的綁定代碼制動確定要使用的正確的形式。
話不多說,直接上例子說用法。
1.bind綁定普通函數(函數指針)
定義函數
int f(int a,int b)
{
return a + b;
}
int g(int a,int b,int c)
{
return a + b + c;
}
typedef int (*f_pointer)(int,int);
typedef int (*g_pointer)(int,int,int);
調用范例
//普通函數
bind(f, 1, 2)(); //f(1,2)
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)
//函數指針
f_pointer fp = f;
g_pointer gp = g;
bind(pf,_1,9); //(*pf)(x,9)
bind(pg,_3,_2,_2)(x,y,z); //(*pg)(z,y,y)
bind有兩個參數表,第一個參數表是bind綁定的函數的參數表(即f和g的參數表),第二個參數表是bind生成的新的對象的參數表,其中,_1,_2…被稱作占位符,至多可以有9個。
2.bind綁定成員函數
類的成員函數必須通過類的對象或者指針調用,因此在綁定時,bind要拿出第一個參數的位置來指定一個類的實例、指針或者引用。
class demo
{
public:
int f(int a,int b){return a + b;}
};
demo a,&ra = a; //類的實例對象和引用
demo * p = & a; //指針
bind(&demo::f,a,_1,20)(10); //a.f(10,20)
bind(&demo::f,ra,_2,_1)(10,20); //a.f(20,10)
bind(&demo::f,p,_1,_2)(10,20); //p->f(10,20)
注意:必須在成員函數前面加上取地址的操作符&。
再舉一個例子:
bind搭配標準算法for_each用來調用容器中所有對象的print()函數
#include <boost/bind/bind.hpp>
using namespace boost;
struct point
{
int x,y;
point(int a = 0,int b = 0):x(a),y(b){}
void print()
{
cout << " ( " << x << " , " << y << " ) \n ";
}
};
int main()
{
vector<point> v(10);
for_each(v.begin(),v.end(),bind(&point::print,_1));
}
這里的for_each()函數的作用是變量v中從begin開始到end結束,每一個成員都要調用print()函數。
3.bind綁定成員變量
bind可以綁定類中的public成員變量,依然用point類來說明。
#include <boost/bind/bind.hpp>
using namespace boost;
struct point
{
int x,y;
point(int a = 0,int b = 0):x(a),y(b){}
};
int main()
{
vector<point> v(10);
vector<int> v2(10);
transform(v.begin().v.end().v2.begin(),bind(&point::x,_1));
}
該例中,transform()函數利用bind講變量v中的成員x全部填入到變量v2中。
4.綁定函數對象
什么是函數對象?你不知道?函數對象其實是一個類的對象,只是因為這個類中重載了操作符,導致該對象調用這個操作符時,形式上看起來像個函數一樣,其實它不是真的函數,不要被誤導了喲。
首先來看一個函數對象的例子。
class FuncObjType
{
public:
void operator()()
{
cout<<"hello C++"<<endl;
}
}
當bind綁定函數對象時,當函數對象有內部類型定義result_type,則bind可以自動推到出返回值類型,但如果函數對象沒用定義result_type,則需要用模板參數指明返回類型:bind<result_type>(functor,...);
由于boost庫中大部分函數對象都有result_type,因此就可以直接使用bind,例如:
bind(std::greater<int>(),_1,10);
bind(std::plus<int>(),_1,_2);
bind(std::modulus<int>(),_1,3);
如果自定義函數對象,沒有result_type的類型定義,就必須顯示地在模板參數中指明bind的返回值類型:
struct func
{
int operator()(int a,int b)
{
return a + b;
}
};
cout<<bind<int>(func::obj(),_1,_2)(10,20)<<endl;
文章參考:
用法講解:不破不立博客
工作機制探究:boost bind初步探究