解析bind1st和bind2nd的使用

解析bind1st和bind2nd的使用 1、首先看一個容器的操作: void f(std::vector<int> &vect) { std::vector<int>::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 <class Arg, class Arg2, class Res> 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, const char *, void> { //其中,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<const char *, int , void> { //其中,int是我們當前iterator值類型,const char *是要傳遞的固定不變的字符串,void是我們func的返回值。看看下面的重載() 聲明,就明白了: public: void operator()(const char *s, int) { // 在這裡添加你想幹的事情,記住,ival就是當前iterator的值, s是需要綁定的不變字符串 } }; 那麼就當然選擇bind1st了,因為需要綁定的不變參數s是第一個參數。 我靠,原來這兩個函數沒什麼本質區別,只是根據用戶定義函數參數的順序有關。 4、現在看看改進後的程序: #include <vector> #include <iostream> #include <functional> #include <iterator> #include <algorithm> void doSomething(const char *c, int i); // 我的第一個二元功能函數, // 首先,我假定doSomething是某個庫函數, // 我並沒有它的源代碼。 // 關於可移植性:MS VC6.0不喜歡在模板的返回類型中使用void, // 所以在MS VC6.0中對operator( )稍作修改,使它返回一個類型(如true) struct doSomethingWrapper : public std::binary_function<const char *, int, void> { // 實際上iValue就是iteraor的derefence值, cValue是不變的捆綁值 void operator()(const char *cValue, int iValue) const { doSomething(cValue, iValue); } }; // 現在,就建立了一個內部的功能函數。 // 關於可移植性,同上。 struct doSomethingDirect : public std::binary_function<const char *, int, void> { void operator()(const char *cValue, int iValue) const { std::cout << cValue << " " << iValue << ". " << std::endl; } }; // 這是個幫助器模板,因為我比較懶,它能減少打字量。 template <class Collection, class Function> Function for_all(Collection &c, const Function &f) { return std::for_each(c.begin(), c.end(), f); } int main() { // 首先,建立vector。 std::vector<int> 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; } /* 運行結果: Wrapper: 1. Wrapper: 2. Wrapper: 3. Wrapper: 4. Wrapper: 5. Wrapper: 6. Wrapper: 7. Wrapper: 8. Wrapper: 9. Direct: 1. Direct: 2. Direct: 3. Direct: 4. Direct: 5. Direct: 6. Direct: 7. Direct: 8. Direct: 9. */ 5、問題思考,如果用bind2nd怎樣實現?自己去想吧!然後對容器的erase的操作就可以用它來實現了 備註:部分測試程序來源於csdn,請原諒我的部分改動!

你可能感兴趣的:(struct,iterator,Class,each,wrapper)