std::function简介及模板类声明

01

std::function简介
std::function是一个函数包装器,该函数包装器模板能包装任何类型的可调用实体,如普通函数,函数对象,lamda表达式等。包装器可拷贝,移动等,并且包装器类型仅仅依赖于调用特征,而不依赖于可调用元素自身的类型。
std::function是c++11的新特性,包含在头文件《functional》中。一个std::function类型对象实例可以包装下列这几种可调用实体:函数、函数指针、成员函数、静态函数、lamda表达式和函数对象。
std::function对象实例可被拷贝和移动,并且可以使用指定的调用特征来直接调用目标元素。当std::function对象实例未包含任何实际可调用实体时,调用该std::function对象实例将抛出std::bad_function_call异常。02

std::function实战
std::function模板类声明
template《class _rp, class 。。._argtypes》 class _libcpp_template_vis function《_rp(_argtypes.。。)》 : public __function::__maybe_derive_from_unary_function《_rp(_argtypes.。。)》, public __function::__maybe_derive_from_binary_function《_rp(_argtypes.。。)》 { 。。. }std::function模板类成员函数声明
typedef _rp result_type; // construct/copy/destroy: _libcpp_inline_visibility function() _noexcept { } _libcpp_inline_visibility function(nullptr_t) _noexcept {} function(const function&); function(function&&) _noexcept; template《class _fp, class = _enableifcallable《_fp》》 function(_fp); #if _libcpp_std_ver 《= 14 template《class _alloc》 _libcpp_inline_visibility function(allocator_arg_t, const _alloc&) _noexcept {} template《class _alloc》 _libcpp_inline_visibility function(allocator_arg_t, const _alloc&, nullptr_t) _noexcept {} template《class _alloc》 function(allocator_arg_t, const _alloc&, const function&); template《class _alloc》 function(allocator_arg_t, const _alloc&, function&&); template《class _fp, class _alloc, class = _enableifcallable《_fp》》 function(allocator_arg_t, const _alloc& __a, _fp __f); #endif function& operator=(const function&); function& operator=(function&&) _noexcept; function& operator=(nullptr_t) _noexcept; template《class _fp, class = _enableifcallable《_fp》》 function& operator=(_fp&&); ~function(); // function modifiers: void swap(function&) _noexcept; #if _libcpp_std_ver 《= 14 template《class _fp, class _alloc》 _libcpp_inline_visibility void assign(_fp&& __f, const _alloc& __a) {function(allocator_arg, __a, _vstd::forward《_fp》(__f)).swap(*this);} #endif // function capacity: _libcpp_inline_visibility _libcpp_explicit operator bool() const _noexcept { return static_cast《bool》(__f_); } // deleted overloads close possible hole in the type system template《class _r2, class.。。 _argtypes2》 bool operator==(const function《_r2(_argtypes2.。。)》&) const = delete; template《class _r2, class.。。 _argtypes2》 bool operator!=(const function《_r2(_argtypes2.。。)》&) const = delete; public: // function invocation: _rp operator()(_argtypes.。。) const; #ifndef _libcpp_no_rtti // function target access: const std::type_info& target_type() const _noexcept; template 《typename _tp》 _tp* target() _noexcept; template 《typename _tp》 const _tp* target() const _noexcept; #endif // _libcpp_no_rtti从成员函数里我们知道std::function对象实例不允许进行==和!=比较操作,std::function模板类实例最终调用成员函数_rp operator()(_argtypes.。。) const进而调用包装的调用实体。1、std::function包装函数指针定义一个std::function《int(int)》对象实例
std::function《int(int)》 callback;std::function对象实例包装函数指针
int (*fun_ptr)(int); int fun1(int a){ return a; } int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; fun_ptr = fun1; //函数指针fun_ptr指向fun1函数 callback = fun_ptr; //std::function对象包装函数指针 std::cout 《《 callback(10) 《《 std::endl; //std::function对象实例调用包装的实体 return 0; }2、std::function包装函数
int fun1(int a){ return a; } int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; callback = fun1; //std::function包装函数 std::cout 《《 callback(42) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }3、std::function包装模板函数
template《typename t》 t fun2(t a){ return a + 2; } int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; callback = fun2《int》; //std::function包装模板函数 std::cout 《《 callback(10) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }4、std::function包装函数对象
struct add{ int operator()(int x){ return x + 9; } }; int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; callback = add(); //std::function包装对象函数 std::cout 《《 callback(2) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }5、std::function包装lamda表达式
int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; auto fun3 = [](int a) {return a * 2;}; //lamda表达式 callback = fun3; //std::function包装lamda表达式 std::cout 《《 callback(9) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }
6、std::function包装模板对象函数
template 《typename t》 struct sub{ t operator()(t a){ return a - 8; } }; int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; callback = sub《int》(); //std::function包装模板对象函数 std::cout 《《 callback(2) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }
7、std::function包装模板对象静态函数
template 《typename t》 struct foo2{ static t foo(t a){ return a * 4; } }; int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; callback = foo2《int》::foo; //std::function包装模板对象静态函数 std::cout 《《 callback(3) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }
8、std::function包装对象静态函数
struct foo1{ static int foo(int a){ return a * 3; } }; int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; callback = foo1::foo; //std::function包装对象静态函数 std::cout 《《 callback(5) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }
9、std::function包装类成员函数
struct foo3{ int foo(int a){ return a * a; } }; int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; foo3 test_foo1; callback = std::bind(&foo3::foo, test_foo1, std::_1); //std::function包装类成员函数 std::cout 《《 callback(9) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }
这里我们用到了std::bind,c++11中std::bind函数的意义就如字面上的意思一样,用来绑定函数调用的某些参数。std::bind的思想其实是一种延迟计算的思想,将可调用对象保存起来,然后在需要的时候再调用。而且这种绑定是非常灵活的,不论是普通函数还是函数对象还是成员函数都可以绑定,而且其参数可以支持占位符。
这里的std::_1是一个占位符,且绑定第一个参数,若可调用实体有2个形参,那么绑定第二个参数的占位符是std::_2。
10、std::function包装模板类成员函数
template 《typename t》 struct foo4{ t foo(t a){ return a * 6; } }; int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; foo4《int》 test_foo2; callback = std::bind(&foo4《int》::foo, test_foo2, std::_1); //std::function包装模板类成员函数 std::cout 《《 callback(7) 《《 std::endl; //std::function对象实例调用包装的调用实体 return 0; }
11、std::function拷贝、移动
int main(int argc, char *argv[]){ std::cout 《《 “hello world” 《《 std::endl; std::function《int(int)》 callback2 = callback; //拷贝赋值运算符 std::cout 《《 callback2(7) 《《 std::endl; std::function《int(int)》&& callback3 = std::move(callback); //移动赋值运算符 std::cout 《《 callback3(7) 《《 std::endl; std::cout 《《 callback(7) 《《 std::endl; std::function《int(int)》 callback4(callback); //拷贝 std::cout 《《 callback4(7) 《《 std::endl; return 0; }


在应用系统中实现多个ADC通道的利弊
LT8610降压型稳压器的性能特点及应用分析
打印机喷头清洗完全流程介绍
Anthony Fernandez为过去一年作出以下总结,亦为其可预见的将来打下强心针
装满资料的硬盘会不会变重
std::function简介及模板类声明
OPPO和vivo与步步高到底什么关系?来理一理
小米10至尊纪念版的两大黑科技:双原生ISO和芯片级单帧逐行HDR
重温魅族Pro5最良心旗舰:一款好产品生在了坏年代
海澜之家投资半导体 是真的吗
徐樑华:坚守碳纤维基础研究,打破国产高性能碳纤维对标困境
T-Box市场研究:市场规模将达百亿,集成化趋势日益明显
智能亚运,盘点蓝牙物联网科技在运动会上的应用
影响宠物DR影像质量的动物和人为因素有哪些?
为什么区块链会被称为颠覆性的技术
部分用户报告苹果macOS Big Sur存在外部显示器连接问题
用于航空电子设计中HMI开发的数据驱动设计
华为ensp模拟器vlan配置命令
受益于联网设备及大数据 芯片业务去年收入3520亿美元
湖北联通将通过5G网络实现工业互联网的数字化转型发展