类模板 std::function 是通用多态函数封装器。 std::function 的实例能存储、复制及调用任何可调用 (Callable) 目标——函数、 lambda 表达式、 bind 表达式或其他函数对象,还有指向成员函数指针和指向数据成员指针。
std::function接收一个函数的类型,而不是函数指针,需要用函数类型实例化该模板。
std::function 满足可复制构造 (CopyConstructible) 和可复制赋值 (CopyAssignable)
- 首先,要区分函数指针和函数类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | void Fun1(){ std::cout<<"Call Fun1()"<<std::endl; } int Fun2(std::string &str){ std::cout<<"Call Fun2()"<<std::endl; } std::vector<int>& Fun3(const int a){ std::cout<<"Call Fun3()"<<std::endl; } 函数指针组成:返回值类型 + 函数指针名 + 函数参数类型 void (*pfunc)() = Fun1; int (*pfunc)(std::string&) = Fun2; std::vector<int>&(*pfunc)(const int) = Fun3; 函数类型:返回值类型 + 函数类型 Fun1的函数类型:void() Fun2的函数类型:int(std::string&) Fun3的函数类型:std::vector<int>&(const int) |
- 函数指针的使用
1 2 3 4 5 6 7 8 9 | //函数指针调用 void(*funptr1)() = Fun1; funptr1(); int(*funptr2)(std::string&) = Fun2; funptr2(str); std::vector<int>&(*funptr3)(const int) =Fun3; funptr3(100); |
- 用普通的函数类型去实例化std::function实例
1 2 3 4 5 6 7 8 9 10 | //用不同类型的全局函数初始化 std::function<void()> fun1 = Fun1; fun1(); std::function<int(std::string&)> fun2 = Fun2; std::string str = "hello"; fun2(str); std::function<std::vector<int>&(const int)> fun3 = Fun3; fun3(10); |
- 使用类的成员方法实例化std::function,并与 map 结合实战
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | void Fun4(){ std::cout<<"Call Fun4()"<<std::endl; } void Fun5(){ std::cout<<"Call Fun5()"<<std::endl; } class MyFunc{ public: void Fun1(){ std::cout<<"Call MyFunc::Fun1()"<<std::endl; } int Fun2(std::string &str){ std::cout<<"Call MyFunc::Fun2()"<<std::endl; } std::vector<int>& Fun3(const int a){ std::cout<<"Call MyFunc::Fun3()"<<std::endl; } }; int main(){ //用类的成员函数初始化 MyFunc mf; std::function<void(MyFunc*)> fun4 = &MyFunc::Fun1; //除静态方法,类的成员对象的调用需要一个this指针,所以隐藏参数为MyFunc* fun4(&mf); std::function<int(MyFunc*,std::string&)> fun5 = &MyFunc::Fun2; fun5(&mf,str); std::function<std::vector<int>&(MyFunc*,const int)> fun6 = &MyFunc::Fun3; fun6(&mf,9); std::map<int,std::function<void()>> FuncMap; /* typedef std::function<void()> MapFunc; //这样可以省事一些 */ FuncMap.insert(std::make_pair<int,std::function<void()>>(0,Fun1)); FuncMap.insert(std::make_pair<int,std::function<void()>>(1,Fun4)); FuncMap.insert(std::make_pair<int,std::function<void()>>(2,Fun5)); //std::map<int,std::function<void()>>::iterator it = FuncMap.begin(); /* for(;it!=FuncMap.end();++it){ it->second(); } */ for(int i = 0 ;i<5;++i){ auto it = FuncMap.find(i); if(it!=FuncMap.end()){ it->second();//调用点 } } return 0; } |
- 用lambad表达式实例化function,或者说用std::function去保留某一种类型的lambda表达式
1 2 | std::function<int(int,int)> Func([](int a,int b)->int{return a+b;}); std::cout<<Func(10,20)<<std::endl; |
- std::function去保留实例化以后的函数模板与函数模版使用
1 2 3 4 5 6 7 8 | template <typename T> void show(const T& a){ std::cout << a << std::endl; } std::function<void(int)> funcc = show<int>; //首先指定模版函数的类型,编译器生成一个int类型的show方法,然后被std::function保留下来 funcc(99); |
- std::function保存自定义函数对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class MyGreater{ public: bool operator()(int& i, int& j)const{ return i > j; } }; std::vector<int> vec; for(int i =0 ;i<10;++i){ vec.push_back(i); } for(auto val:vec){ std::cout<<val<<" "; } std::cout<<"\n"; std::function<bool(int,int)> fun_ = MyGreater(); std::sort(vec.begin(),vec.end(),fun_); for(auto val:vec){ std::cout<<val<<" "; } std::cout<<"\n"; //如果MyGreater是类模板,实例化function时: std::function<bool(int,int)> func = MyGreater<int>(); |
总结一句话:
std::function可以保留可调用目标,包括如生命周期等于语句的生命周期的lambada表达式等。使用的时候用可调用目标的类型(函数类型)去实例化一个function类,调用的时候实际上调用的是生成function对象的operator()方法。
参考链接: std::function