(轉)解析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.
*/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM