bind1st : operator()的第一个形参变量绑定成一个确定的值
bind2nd : operator()的第二个形参变量绑定成一个确定的值
绑定器 + 二元函数对象 =》 一元函数对象
把70按顺序插入到vec容器当中 找第一个小于70的数字 operator()(const T &val) greater a > b less a < b 绑定器 + 二元函数对象 =》 一元函数对象 bind1st: + greater bool operator()(70, const _Ty& _Right) bind2nd: + less bool operator()(const _Ty& _Left, 70)
auto it1 = my_find_if(vec.begin(), vec.end(), mybind1st(greatermy_find_if(), 70)); //auto it1 = my_find_if(vec.begin(), vec.end(), //bind2nd(less (), 70)); if (it1 != vec.end()) { vec.insert(it1, 70); } showContainer(vec);
遍历俩个迭代器区间,如果满足comp运算,返回当前迭代器,如果都不满足,返回end
template_mybind1st实现Iterator my_find_if(Iterator first, Iterator last, Compare comp) { for (; first != last; ++first) { if (comp(*first)) // comp.operator()(*first) { return first; } } return last; }
templatefunctionclass _mybind1st // 绑定器是函数对象的一个应用 { public: _mybind1st(Compare comp, T val) :_comp(comp), _val(val) {} bool operator()(const T &second) { return _comp(_val, second); // greater } private: Compare _comp; T _val; }; template _mybind1st mybind1st(Compare comp, const T &val) { // 直接使用函数模板,好处是,可以进行类型的推演 return _mybind1st (comp, val); }
留下函数对象,lambda表达式的类型留下来
1.用函数类型实例化function
2.通过function调用operator()函数的时候,需要根据函数类型传入相应的参数
void hello1()
{
cout << "hello world!" << endl;
}
void hello2(string str) // void (*pfunc)(string)
{
cout << str << endl;
}
class Test
{
public: // 必须依赖一个对象void (Test::*pfunc)(string)
void hello(string str) { cout << str << endl; }
};
function func1 = hello1;
func1(); // func1.operator()() => hello1()
function func2 = hello2;
func2("hello hello2!"); // func2.operator()(string str) => hello2(str)
// operator()
function func4 = [](int a, int b)->int {return a + b; };
cout << func4(100, 200) << endl;
function func5 = &Test::hello;
func5(&Test(), "call Test::hello!");
使用function的好处
下面这块代码会随着我们需要的更改然后改来改去,不好维护,无法做到“开闭原则”
int choice = 0; // C的函数指针 map> actionMap; actionMap.insert({ 1, doShowAllBooks }); // insert(make_pair(xx,xx)); actionMap.insert({ 2, doBorrow }); actionMap.insert({ 3, doBack }); actionMap.insert({ 4, doQueryBooks }); actionMap.insert({ 5, doLoginOut }); for (;;) { cout << "-----------------" << endl; cout << "1.查看所有书籍信息" << endl; cout << "2.借书" << endl; cout << "3.还书" << endl; cout << "4.查询书籍" << endl; cout << "5.注销" << endl; cout << "-----------------" << endl; cout << "请选择:"; cin >> choice; auto it = actionMap.find(choice); // map pair first second if (it == actionMap.end()) { cout << "输入数字无效,重新选择!" << endl; } else { it->second(); } // 不好,因为这块代码无法闭合 无法做到“开-闭原则 }
而我们使用function之后
void doShowAllBooks() { cout << "查看所有书籍信息" << endl; }
void doBorrow() { cout << "借书" << endl; }
void doBack() { cout << "还书" << endl; }
void doQueryBooks() { cout << "查询书籍" << endl; }
void doLoginOut() { cout << "注销" << endl; }
map> actionMap;
actionMap.insert({ 1, doShowAllBooks }); // insert(make_pair(xx,xx));
actionMap.insert({ 2, doBorrow });
actionMap.insert({ 3, doBack });
actionMap.insert({ 4, doQueryBooks });
actionMap.insert({ 5, doLoginOut });
auto it = actionMap.find(choice); // map pair first second
if (it == actionMap.end())
{
cout << "输入数字无效,重新选择!" << endl;
}
else
{
it->second();
}
function的底层原理
模板的完全特例化和非完全(部分)特例化
emplateclass Vector { public: Vector() { cout << "call Vector template init" << endl; } }; // 下面这个是对char*类型提供的完全特例化版本 #1 template<> class Vector { public: Vector() { cout << "call Vector init" << endl; } }; // 下面这个是对指针类型提供的部分特例化版本 #2 template class Vector { public: Vector() { cout << "call Vector init" << endl; } }; // 指针函数指针(有返回值,有两个形参变量)提供的部分特例化 template class Vector { public: Vector() { cout << "call Vector init" << endl; } }; // 针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化 template class Vector { public: Vector() { cout << "call Vector init" << endl; } };
Vector模板实参推演vec1; Vector vec2; Vector vec3; Vector vec4; Vector vec5; // function
templatefunction函数对象类型的实现原理bool compare(T a, T b) { cout << "template compare" << endl; return a > b; } template<> bool compare (const char*a, const char*b) { cout << "compare " << endl; return strcmp(a, b) > 0; } int main() { compare(10, 20); // compare("aaa", "bbb"); // T const char* return 0; }
templateclass myfunction { public: using PFUNC = R(*)(A1); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A1 arg) { return _pfunc(arg); // hello(arg) } private: PFUNC _pfunc; }; template class myfunction { public: using PFUNC = R(*)(A1, A2); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A1 arg1, A2 arg2) { return _pfunc(arg1, arg2); // hello(arg) } private: PFUNC _pfunc; };
利用template的强大机制,用…表示多个传入的参数。
避免了因为参数的个数不同重写多个myfunction
templatebindclass myfunction { public: using PFUNC = R(*)(A...); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A... arg) { return _pfunc(arg...); // hello(arg) } private: PFUNC _pfunc; }; int main() { function func1(hello); func1("hello world!"); // func1.operator()("hello world!") myfunction func2(sum); cout << func2(10, 20) << endl; return 0; }
bind绑定器 =》 返回的结果还是一个函数对象
bind 是个函数模板,可以自动推演模板类型参数
()小括号是运算符重载函数
void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
class Test
{
public:
int sum(int a, int b) { return a + b; }
};
int main()
{
// bind是函数模板 可以自动推演模板类型参数
bind(hello, "hello bind!")();
cout << bind(sum, 10, 20)() << endl;
cout << bind(&Test::sum, Test(), 20, 30)() << endl;
// 参数占位符 绑定器出了语句,无法继续使用
bind(hello, _1)("hello bind 2!");
cout << bind(sum, _1, _2)(200, 300) << endl;
// 此处把bind返回的绑定器binder就复用起来了
function func1 = bind(hello, _1);
func1("hello china!");
func1("hello shan xi!");
func1("hello si chuan!");
return 0;
}
lambda
C++11 函数对象的升级版 =》 lambda表达式
函数对象的缺点:
使用在泛型算法参数传递 比较性质/自定义操作 优先级队列 智能指针
lambda表达式的语法:
捕获外部变量->返回值{操作代码};
如果lambda表达式的返回值不需要,那么"->返回值"可以省略的
[捕获外部变量]
[]:表示不捕获任何外部变量
[=]:以传值的方式捕获外部的所有变量
[&]:以传引用的方式捕获外部的所有变量
[this]:捕获外部的this指针
[=,&a]:以传值的方式捕获外部的所有变量,但是a变量以传引用的方式捕获
[a, b]:以值传递的方式捕获外部变量a和b
[a, &b]:a以值传递捕获,b以传引用的方式捕获



