C++ | function
文章目录
- C++ | function
- 引言
- 实战
- 1. 模板类声明
- 2.普通函数/Lambda表达式/仿函数/类成员函数
- 3.函数指针/模板函数/模板函数对象
- 4.静态函数/类模板静态函数/模板类成员函数/类成员函数
- 5. copy/move
- Reference
引言
程序设计时,经常需要使用回调函数,如果针对每种不同的可调用对象或函数单独进行声明类型,代码会非常冗余。
因此C++ 引入了std::function
类模板,std::function对象实例可被拷贝,移动等,可以使用指定的调用特征来直接调用目标元素,不依赖于其元素自身的类型。
该函数包装器模板能包装任何类型的可调用实体,如普通函数、函数对象、成员函数、静态函数、lamda表达式和函数对象等。
当std::function对象实例未包含任何实际可调用实体时,调用该std::function对象实例将抛出std::bad_function_call异常。
可调用对象(callable object)包括:
- 函数
- 函数指针
- lambda 表达式
- bind 创建的对象
- 重载了函数调用运算符的类(仿函数)
实战
1. 模板类声明
简单说,std::function 就是提前存储了函数实体,在需要的时候回调出来即可。其入参和返回值均与被调用函数保持一致。
如果绑定函数实体的时候,还没确定函数参数,可以通过 std::bind 进行函数入参绑定,等到参数确定好,再传入合适的位置以供调用。
/** _Res 是返回类型, _ArgTypes 是参数类型
* @brief Primary class template for std::function.
* @ingroup functors
*
* Polymorphic function wrapper.
*/
template<typename _Res, typename... _ArgTypes>
class function<_Res(_ArgTypes...)>
: public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
private _Function_base
{
template<typename _Func,
typename _Res2 = __invoke_result<_Func&, _ArgTypes...>>
struct _Callable
: __is_invocable_impl<_Res2, _Res>::type
{ };
// Used so the return type convertibility checks aren't done when
// performing overload resolution for copy construction/assignment.
template<typename _Tp>
struct _Callable<function, _Tp> : false_type { };
template<typename _Cond, typename _Tp>
using _Requires = typename enable_if<_Cond::value, _Tp>::type;
public:
typedef _Res result_type;
// [3.7.2.1] construct/copy/destroy
function() noexcept
: _Function_base() { }
function(nullptr_t) noexcept
: _Function_base() { }
function(const function& __x);
function(function&& __x) noexcept : _Function_base()
{
__x.swap(*this);
}
// ======================= Randy 还有诸多成员函数 =======================
/** 只能和 nullptr 和 0 比较
* @brief Compares a polymorphic function object wrapper against 0
* (the NULL pointer).
* @returns @c false if the wrapper has no target, @c true otherwise
*
* This function will not throw an %exception.
*/
template<typename _Res, typename... _Args>
inline bool
operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
{ return static_cast<bool>(__f); }
/// @overload
template<typename _Res, typename... _Args>
inline bool
operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
{ return static_cast<bool>(__f); }
private:
using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
_Invoker_type _M_invoker;
};
因此,定义一个std::function 的时候,需要将入参及返回值传递给 std::function 模板类即可
std::function<std::string(int)> randy;
std::function<int(char,double)> sesame;
2.普通函数/Lambda表达式/仿函数/类成员函数
#include <iostream>
#include <functional>
// 普通函数
int commonFunc(int lhs, int rhs) {
return lhs + rhs;
}
// Lambda表达式
auto lamdaFunc = [](int lhs, int rhs) {
return lhs + rhs;
};
// 函数对象 换成 struct 亦可
class Functor {
public:
int operator()(int lhs, int rhs) {
return lhs + rhs;
}
};
// 类成员函数
class Randy
{
public:
// 1.类成员函数
int RandyMemberFunc(int lhs, int rhs) { return lhs + rhs; }
// 2.类静态成员函数
static int RandyStaticFunc(int lhs, int rhs) { return lhs + rhs; }
};
int main() {
// 定义一个 std::function 函数
std::function<int(int, int)> qcj_CallBack;
int result = -1;
// 普通函数
qcj_CallBack = commonFunc;
result = qcj_CallBack(2, 1);
std::cout << "common function: " << result << std::endl;
// 普通函数指针
qcj_CallBack = &commonFunc;
result = qcj_CallBack(2 ,2);
std::cout << "common function pointer: " << result << std::endl;
// Lambda表达式
qcj_CallBack = lamdaFunc;
result = qcj_CallBack(2, 3);
std::cout << "lambda function: " << result << std::endl;
// 函数对象
Functor functor_randy;
qcj_CallBack = functor_randy;
result = qcj_CallBack(2, 4);
std::cout << "function object: " << result << std::endl;
// 类成员函数(使用std::bind绑定类成员函数, std::placeholders::_2为占位符,顺序与原函数入参对应,次序可调换)
// qcj_CallBack = std::bind(&Randy::RandyMemberFunc, randy, std::placeholders::_2, std::placeholders::_1);
// 上式这么写也可以,调用时 第2个入参在前,第1个入参在后
Randy randy;
qcj_CallBack = std::bind(&Randy::RandyMemberFunc, randy, std::placeholders::_1, std::placeholders::_2);
result = qcj_CallBack(2, 5);
std::cout << "class member function: " << result << std::endl;
// 类静态成员函数
qcj_CallBack = Randy::RandyStaticFunc;
result = qcj_CallBack(2, 6);
std::cout << "class static member function: " << result << std::endl;
return 0;
}
结果:
common function: 3
common function pointer: 4
lambda function: 5
function object:: 6
class member function: 7
class static member function: 8
3.函数指针/模板函数/模板函数对象
#include <iostream>
#include <functional>
// 回调函数
std::function<std::string(std::string)> RandyFuncCallBack;
// 函数指针
std::string (*RandyFuncPtr)(std::string);
template<typename T>
T RandyTemplate(T t_arg){
return "三戒纪元: " + t_arg;
}
// 模板函数对象
template <typename T>
struct RandyStruct{
T operator()(T t_arg){
return "Randy struct: " + t_arg;
}
};
int main(int argc, char *argv[]){
//std::function包装模板函数
RandyFuncCallBack = RandyTemplate<std::string>;
std::cout << RandyFuncCallBack("std::function called.") << std::endl;
// 函数指针
RandyFuncPtr = RandyTemplate;
RandyFuncCallBack = RandyFuncPtr;
std::cout << RandyFuncCallBack("function ptr called.") << std::endl;
// 模板函数对象
RandyFuncCallBack = RandyStruct<std::string>();
std::cout << RandyFuncCallBack("struct function called.") << std::endl;
return 0;
}
结果:
三戒纪元: std::function called.
三戒纪元: function ptr called.
Randy struct: struct function called.
4.静态函数/类模板静态函数/模板类成员函数/类成员函数
#include <iostream>
#include <functional>
// 回调函数
std::function<std::string(std::string)> RandyFuncCallBack;
// 类成员函数
struct Randy{
std::string RandyCommonFunc(std::string sesame){
return "Randy common function: " + sesame;
}
static std::string RandyStaticFunc(std::string t_arg){
return "Randy static function: " + t_arg;
}
};
// 模板类
template <typename T>
struct RandyTemplateStruct{
// 模板对象函数
T RandyTemplateFunc(T sesame){
return "Randy Template function: " + sesame;
}
// 模板对象静态函数
static T RandyTemplateStaticFunc(T t_arg){
return "Randy Template static function: " + t_arg;
}
};
int main(int argc, char *argv[]){
Randy randy;
// 类成员函数
RandyFuncCallBack = std::bind(&Randy::RandyCommonFunc, &randy, std::placeholders::_1);
std::cout << RandyFuncCallBack("RandyCommonFunc called.") << std::endl;
// 类成员函数
RandyFuncCallBack = randy.RandyStaticFunc;
std::cout << RandyFuncCallBack("RandyStaticFunc called.") << std::endl;
// 模板对象函数
RandyTemplateStruct<std::string> randyTemplate;
RandyFuncCallBack = std::bind(&RandyTemplateStruct<std::string>::RandyTemplateFunc, &randyTemplate, std::placeholders::_1);
std::cout << RandyFuncCallBack("RandyTemplateFunc called.") << std::endl;
// 模板对象静态函数
RandyFuncCallBack = RandyTemplateStruct<std::string>::RandyTemplateStaticFunc;
std::cout << RandyFuncCallBack("RandyTemplateStaticFunc called.") << std::endl;
return 0;
}
结果:
Randy common function: RandyCommonFunc called.
Randy static function: RandyStaticFunc called.
Randy Template function: RandyTemplateFunc called.
Randy Template static function: RandyTemplateStaticFunc called.
5. copy/move
#include <iostream>
#include <functional>
// 回调函数
std::function<std::string(std::string)> RandyFuncCallBack;
std::string PrintRandy(std::string sesame) {
return ">>>>>>>>>> 三戒纪元: " + sesame + " <<<<<<<<<<";
}
int main(int argc, char *argv[]){
// 未包装任何对象实体
std::cout << RandyFuncCallBack("RandyFuncCallBack") << std::endl;
// 结果为:Aborted (core dumped)
RandyFuncCallBack = PrintRandy;
std::cout << RandyFuncCallBack("RandyFuncCallBack") << std::endl;
//拷贝
std::function<std::string(std::string)> CallBack_Copy(RandyFuncCallBack);
std::cout << CallBack_Copy("CallBack_Copy") << std::endl;
//拷贝赋值运算符
std::function<std::string(std::string)> CallBack_CopyAssign = RandyFuncCallBack;
std::cout << CallBack_CopyAssign("CallBack_CopyAssign.") << std::endl;
//移动赋值运算符
std::function<std::string(std::string)>&& CallBack_MoveAssign = std::move(RandyFuncCallBack);
std::cout << CallBack_MoveAssign("CallBack_MoveAssign") << std::endl;
std::cout << RandyFuncCallBack("RandyFuncCallBack") << std::endl;
return 0;
}
结果:
>>>>>>>>>> 三戒纪元: RandyFuncCallBack <<<<<<<<<<
>>>>>>>>>> 三戒纪元: CallBack_Copy <<<<<<<<<<
>>>>>>>>>> 三戒纪元: CallBack_CopyAssign. <<<<<<<<<<
>>>>>>>>>> 三戒纪元: CallBack_MoveAssign <<<<<<<<<<
>>>>>>>>>> 三戒纪元: RandyFuncCallBack <<<<<<<<<<
Reference
-
【C++11 新特性】function(一)
-
C++ std::function详解与实战
欢迎关注公众号【三戒纪元】