(转)解析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.    
*/
 
                    
                 
                
            
         
 浙公网安备 33010602011771号
浙公网安备 33010602011771号