bind绑定器和function函数对象
1.函数对象operator();
一元函数对象,operator()(const T&val ),括号里面只有一个
二元函数对象,operator()(const T&val,const T&val2 ),括号里面有2个
2.绑定器
bind1st :operator()是一个函数适配器,它的作用是将一个值绑定到二元函数对象的第一个参数,从而创建一个新的一元函数对象。
bind2nd :operator()是一个函数适配器,它的作用是将一个值绑定到二元函数对象的第二个参数上,从而创建一个新的一元函数对象。
find_if(vec.begin(),vec.end(),一元函数对象);
但是great less 是二元, 所以要用到绑定器
绑定器+二元函数对象=》一元函数对象
bind1st + greater bool operator() (70, const _Ty& _Right)
bind2nd: + less bool operator()(const _Ty&Left,70)
greater a>b
less a<b
下面都是返回一个第一个大于70的元素,如果没有这样的元素,则迭代器it1/2将等于vec.end()。
auto it1=find_if(vec.begin(),vec.end(),bind1st(greater<int>(),70))//70>value
auto it2=find_if(vec.begin(),vec.end(),bind2nd(less<int>(),70))//value<70
3.c++11从boost库引入bind绑定器和function函数对象机制
4.lambda表达式 底层依赖函数对象机制的实现
sort(vec.begin(),vec.end())//小到大
sort(vec.begin(),vec.end(),greater<int>());//从大到小排序,默认小到大
sort(vec.begin(),vec.end(),[](int a, int b) { return a > b; });//从大到小排序,默认小到大
[]不捕获外部变量
[=] 以传值方式捕获
[&]以传引用的方式捕获
[this]捕获外部的this
[=,&a]以传值捕获,但是a传引用捕获
[this]捕获外部this
[a,b]以值传递的方式捕获外部变量a和b
语法:
[捕获外部变量](形参)->返回值{操作代码}
auto fun3=[&](){
int tmp=a;
a=b;
b=tmp;
}
或者
auto fun3=[&a,&b](){
int tmp=a;
a=b;
b=tmp;
}
fun3();
5.function函数对象
lambda表达式,它们只能使用在一个语句中,但是function让其可以多条使用
从function的类模板定义出看到希望用一个函数类型实例化function
function<void()>func1=hello1;
func1(); //func1.operator()=>hello1()
function<void(string)>func2=hello2;
func2("hello hello ");//func2.operator()(string str)=>hello2(str);
function<int(int,int)>func4=[](int a,int b)->int{return a+b;}
func3(100,200);//300
其实就是用func2替代了那个函数对象,进行包装调用的时候传入参数
1.用函数类型实例化function
2.通过function调用operator()函数的时候,需要根据函数类型传入参数
类的成员调用必须要成员对象
void (Test::*pfunc)(string)//调用
function<void(Test*,string)>func4=&Test::hello;
func4(&Test(),"call test::hello");
普通函数不用
void(*pfunc)(string);
function 可以用map将数字和函数结合起来
然后调用的数字就执行相应的函数,比较好的功能
map<int, function<int(int, int)>> calc_map;
calc_map[1] = [](int a, int b)->int {return a + b; };
calc_map[2] = [](int a, int b)->int {return a - b; };
calc_map[3] = [](int a, int b)->int {return a * b; };
calc_map[4] = [](int a, int b)->int {return a / b; };
又比如选择不同数字对应不同的书籍 key:数字 value:书籍
6.模板的完全特例化和非完全(部分)特例化
有原模板才能提供完全特例化
template<typename T>
bool compare(T a,T b){
return a>b;
}
template<>//完全特例化
bool compare<const char*>(const char* a,const char* b)
{
return strcmp(a,b)>0;
}
int main(){
compare(10,20)//int
compare("aa","bb");//T const char*
}
7.function的实现原理
#include <iostream>
#include <typeinfo>
#include <string>
#include <functional>
using namespace std;
// 先提供统一的模板
template<typename T>
class MyFunction {
};
// 根据具体情况细分(返回值和单个形参)
template<typename R, typename A1>
class MyFunction<R(A1)> {
public:
using PFUNC = R(*)(A1);
MyFunction(PFUNC pfunc) :_pfunc(pfunc) {
}
R operator()(A1 arg) {
return _pfunc(arg);
}
private:
PFUNC _pfunc;
};
int print(string str) {
cout << str << endl;
return str.size();
}
int main() {
MyFunction<int(string)> func(print);
int len = func("hello world"); //func.operator()("hello world")
cout << len << endl;
return 0;
}
using 可以重新定义函数名
using PFUNC = R(*)(A1);:这里使用 using 关键字定义了一个类型别名 PFUNC。PFUNC 是一个指向函数的指针,该函数接受一个类型为 A1 的参数并返回类型为 R 的值。换句话说,PFUNC 是一个函数指针类型,它可以指向任何符合这个签名的函数。
可变参数… 可以接受一组形参变量
7.bind绑定器=》返回结果还是一个函数对象,功能比bind1st和bind2nd强大
需要operator()重载函数
#include <iostream>
#include <functional>
#include <string>
#include <typeinfo>
using namespace std;
void show(string str) {
cout << str << endl;
}
void add1(int a, int b) {
cout << a + b << endl;
}
class Test {
public:
void add2(int a, int b) {
cout << a + b << endl;
}
};
int main() {
bind(show, "hello")(); // bind(show, "hello")返回的是function<void()>函数对象
bind(add1, 1, 2)(); // bind(add1, 1, 2)返回的是function<void()>函数对象
bind(&Test::add2, Test(), 1, 2)();
// 使用类型占位符,后续调用时再传
// bind(show, placeholders::_1)返回的是function<void(string)>函数对象
bind(show, placeholders::_1)("hello");
// 最多绑定_20参数
// bind(add1, placeholders::_1, placeholders::_2)返回的是function<void(int, int)>函数对象
function<void(int, int)> func = bind(add1, placeholders::_1, placeholders::_2);
func(1, 2);
return 0;
}
//参数占位符
bind(hello,placeholders::_1)("hello bind 2");
bind(sum,placeholders::_1,placeholders::_2)(200,300);
//绑定器出了语句无法继续使用=》function
function<void(string )>func1=bind(hello,placeholders::_1);
func1("hello ");//此处可以将bind返回的绑定器binder复用起来