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详解与实战 
欢迎关注公众号【三戒纪元】



















