zoukankan      html  css  js  c++  java
  • (转)解析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.
    */

    敦品厚德 格物致知
  • 相关阅读:
    js判断空对象
    浅析css布局模型2
    Python 绘图
    我的第一个 Kaggle 比赛学习
    写代码 Log 也要认真点么?
    Python 线性回归(Linear Regression)
    Python
    Git
    算法4:插入排序和选择排序算法的比较
    《算法4》2.1
  • 原文地址:https://www.cnblogs.com/crunchyou/p/2762178.html
Copyright © 2011-2022 走看看