C++ 11 bind
2015-10-20 17:52
316 查看
bind是一组用于函数绑定的模板。在对某个函数进行绑定时,可以指定部分参数或全部参数,也可以不指定任何参数,还可以调整各个参数间的顺序。对于未指定的参数,可以使用占位符_1、_2、_3来表示。-1表示绑定后的函数的第1个参数,_2表示绑定后的函数的第2个参数,其他依次类推。bind可以绑定到普通函数、函数对象、类的成员函数和类的成员变量。下面分别进行介绍。
1、普通函数
void nine_arguments(int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9);
int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9;
bind(nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7(i1,i2,i3,i4,i5,i6,i7,i8,i9);
bind(nine_arguments,i9,i2,i1,i6,i3,i8,_1,_2,_1)(i8,i9);
bind(nine_arguments, i9,i2,i1,i6,i3,i8,i4,i5,i7)();
2、函数对象
3、类的成员函数
struct TAdd
{
int Add(int x,int y)
{
return x+y;
}
};
TAdd tAdd;
TAdd *p = new TAdd();
shared_ptr<TAdd> *q(p);
bind(TAdd::Add, tAdd, 2, 3)();
bind(TAdd::Add, p, 2, 3)();
bind(TAdd::Add, q, 2, 3)();
4、类的成员变量
void Output(const string &name)
{
cout << name << endl;
}
map<int, string> map1;
for_each(map1.begin(), map1.end(), bind(Output, bind(map<int,string>::value_type::second, _1)));
bind还可以进行嵌套绑定。假设有一个CPerson类,该类有一个获取年龄的接口int GetAge(),现在有一个CPerson对象的vector,需要对其进行排序,则可以如下使用bind:
vector<CPerson> vctPerson;
sort(vctPerson.begin(), vctPerson.end(), bind(less<int>(),
bind(CPerson::GetAge, _1), bind(CPerson::GetAge, _2)));假设有一个整数的vector, 现在想要获取其中大于20但小于30的整数的个数,则有:
1、对于指定了值的参数,bind返回的函数对象会保存这些值,并且缺省是以传值方式保存的。考虑下面的代码:
void inc(int &a) { a++; }
int n = 0;
bind(inc, n)();调用bind返回的函数对象后,n仍然等于0。这是由于bind时,传入的是n的拷贝。如果需要传入n的引用,则可以使用ref或cref函数,比如:
2、bind的第一个参数是一个函数对象,不能用占位符来代替。考虑下面的代码:
typedef function<void (int)> Func;
vector<Func> vctFunc;
for_each(vctFunc.begin(), vctFunc.end(), bind(_1, 5)); // 编译出错此时,可以借助apply模板。apply模板的第一个参数是传入的函数对象,后面可以有若干个参数,表示函数对象的参数。比如:
1、普通函数
void nine_arguments(int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9);
int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9;
bind(nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7(i1,i2,i3,i4,i5,i6,i7,i8,i9);
bind(nine_arguments,i9,i2,i1,i6,i3,i8,_1,_2,_1)(i8,i9);
bind(nine_arguments, i9,i2,i1,i6,i3,i8,i4,i5,i7)();
2、函数对象
class CStudent { public: void operator() (string strName, int nAge) { cout << strName << " : " << nAge << endl; } }; bind(CStudent(), "Mike", _1)(12);
3、类的成员函数
struct TAdd
{
int Add(int x,int y)
{
return x+y;
}
};
TAdd tAdd;
TAdd *p = new TAdd();
shared_ptr<TAdd> *q(p);
bind(TAdd::Add, tAdd, 2, 3)();
bind(TAdd::Add, p, 2, 3)();
bind(TAdd::Add, q, 2, 3)();
4、类的成员变量
void Output(const string &name)
{
cout << name << endl;
}
map<int, string> map1;
for_each(map1.begin(), map1.end(), bind(Output, bind(map<int,string>::value_type::second, _1)));
bind还可以进行嵌套绑定。假设有一个CPerson类,该类有一个获取年龄的接口int GetAge(),现在有一个CPerson对象的vector,需要对其进行排序,则可以如下使用bind:
vector<CPerson> vctPerson;
sort(vctPerson.begin(), vctPerson.end(), bind(less<int>(),
bind(CPerson::GetAge, _1), bind(CPerson::GetAge, _2)));假设有一个整数的vector, 现在想要获取其中大于20但小于30的整数的个数,则有:
count_if(vctNum.begin(), vctNum.end, bind(logic_and<bool>(), bind(greater<int>(), _1, 20), bind(less<int>(), _1, 30)));在使用bind时,还有一些需要特别注意的地方,下面逐一进行介绍。
1、对于指定了值的参数,bind返回的函数对象会保存这些值,并且缺省是以传值方式保存的。考虑下面的代码:
void inc(int &a) { a++; }
int n = 0;
bind(inc, n)();调用bind返回的函数对象后,n仍然等于0。这是由于bind时,传入的是n的拷贝。如果需要传入n的引用,则可以使用ref或cref函数,比如:
bind(inc, ref(n))(); // n现在等于1了
2、bind的第一个参数是一个函数对象,不能用占位符来代替。考虑下面的代码:
typedef function<void (int)> Func;
vector<Func> vctFunc;
for_each(vctFunc.begin(), vctFunc.end(), bind(_1, 5)); // 编译出错此时,可以借助apply模板。apply模板的第一个参数是传入的函数对象,后面可以有若干个参数,表示函数对象的参数。比如:
apply<void> a; // void是函数对象的返回值类型 a(f); // 相当于调用f() a(f, x); // 相当于调用f(x) a(f, x, y); // 相当于调用f(x, y)使用apply后,我们可以将vctFunc中的元素当作占位符传递过来。参考代码如下:
for_each(vctFunc.begin(), vctFunc.end(), bind(apply<void>(), _1, 5));
相关文章推荐
- c语言学习笔记(15) 数组基础
- C语言(8) 变量在内存中的分配原则
- C语言(7) 模块化编程及多文件开发注意事项
- C语言(4) 原码、反码、补码与位运算
- C++ 11 function
- C语言(6) unix命令/C手动编译/include指令/Xcode 清空缓存的方法
- C++ 11 tuple & 可变参数模板
- C语言(5) 函数使用需要注意的地方
- 《C++ Primer 5th edition》 第一章 开始
- C++ 11语法甜点2
- c语言函数指针的定义
- 【好玩的棋盘游戏】编写一个玩家操作的函数和电脑能够操作的两人棋盘游戏,哪边有三个相连的胜出
- C语言--字符串处理函数的使用
- VC++ 关机代码
- C++ 11语法甜点1
- 【经典游戏编程题】C语言:编写一个棋盘游戏,与二维数组结合
- C语言(3) 运算符及优先级
- C++单根类的实现
- c++类静态成员详解
- C++ 11完美转发