Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2570213
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: C/C++

2013-05-05 00:34:59

 

解析bind1st和bind2nd的使用

解析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;
}


/* 运行结果:
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的操作就可以用它来实现了

作者:【】http://blog.csdn.net/ych1/article/details/1430419
阅读(846) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~