解析bind1st和bind2nd的使用
1、首先看一個容器的操作:
void f(std::vector &vect)
{
std::vector::iterator firstOne;
for (firstOne = vect.begin();
firstOne != vect.end();
++firstOne)
{
doSomething(*firstOne, "Some string literal");
}
}
這個f調用就是完成對容器vect的疊代,並在疊代過程中,處理iter值和一個不變的字元串,至於dosomething完成什麼功能,根本不必關心。
這裡有人肯定要說,不是用for_each就可完成這種功能嗎,可for_each隻接受一個參數的函數。如下所示:
funcation for_each(iterator beg_it, iterator end_it, funcation func);
那麼怎樣讓func能夠綁定當前iterator值和一個不變的字元串呢?如果成功,問題就OK了。
在解決這個問題必須要用到適配器函數,如bind1nd, bind2st之流的捆綁函數。在解析這兩個函數之前,先看看Funcation的類聲明:
2、Funcation的類聲明:
template
struct binary_function {
typedef Arg first_argument_type;
typedef Arg2 second_argument_type;
typedef Res result_type;
};
ok, 我們自己的func也可繼承這個基類,哈哈,改進後的dosomething聲明:
class dosomething:public
std::binary_funcation
{
//其中,int是我們當前iterator值類型,const char *是要傳遞的固定不變的字元串,void是我們func的傳回值。看看下面的重載() 聲明,就明白了:
public:
void operator()(int ival, const char *s)
{
// 在這裡添加你想幹的事情,記住,ival就是當前iterator的值, s是需要綁定的不變字元串
}
};
3、bind1st和bind2nd的選擇
從如上的dosomething可以看出,需要綁定的是s這個不變字元串,是第二個參數,是以當然選擇bind2nd,如果dosomething的聲明如下:
class dosomething:public
std::binary_funcation
{
//其中,int是我們當前iterator值類型,const char *是要傳遞的固定不變的字元串,void是我們func的傳回值。看看下面的重載() 聲明,就明白了:
public:
void operator()(const char *s, int)
{
// 在這裡添加你想幹的事情,記住,ival就是當前iterator的值, s是需要綁定的不變字元串
}
};
那麼就當然選擇bind1st了,因為需要綁定的不變參數s是第一個參數。
我靠,原來這兩個函數沒什麼本質區別,隻是根據用戶定義函數參數的順序有關。
4、現在看看改進後的程式:
#include
#include
#include
#include
#include
void doSomething(const char *c, int i);
// 我的第一個二進制功能函數,
// 首先,我假定doSomething是某個庫函數,
// 我並沒有它的源代碼。
// 關於可移植性:MS VC6.0不喜歡在模闆的傳回類型中使用void,
// 是以在MS VC6.0中對operator( )稍作修改,使它傳回一個類型(如true)
struct doSomethingWrapper : public
std::binary_function
{
// 實際上iValue就是iteraor的derefence值, cValue是不變的捆綁值
void operator()(const char *cValue, int iValue) const
{
doSomething(cValue, iValue);
}
};
// 現在,就建立了一個內部的功能函數。
// 關於可移植性,同上。
struct doSomethingDirect : public
std::binary_function
{
void operator()(const char *cValue, int iValue) const
{
std::cout << cValue
<< " "
<< iValue
<< ". " << std::endl;
}
};
// 這是個幫助器模闆,因為我比較懶,它能減少打字量。
template
Function for_all(Collection &c, const Function &f)
{
return std::for_each(c.begin(), c.end(), f);
}
int main()
{
// 首先,建立vector。
std::vector vect;
for (int i=1; i<10; ++i) {
vect.push_back(i);
}
for_all(vect, std::bind1st(doSomethingWrapper(), "Wrapper:"));
std::cout << "/n";
for_all(vect, std::bind1st(doSomethingDirect(), "Direct:"));
getchar();
return 0;
}
// 我獨樹一幟的第三方庫函數
void doSomething(const char *c, int i)
{
std::cout << c << " " << i << ". " << std::endl;
}
5、問題思考,如果用bind2nd怎樣實現?自己去想吧!然後對容器的erase的操作就可以用它來實現了
備註:部分測試程式來源於csdn,請原諒我的部分改動!