std::function的实现
【基本概念】
- std::function:可调用对象包装器,是C++11新标准引入的类模板。
- 需要添加头文件:#include <functional>
- 函数名(函数指针)、具有operator()成员函数的类对象、lambda表达式等等,都属于可调用对象。
【引例】
void myfunc(int tmpvalue) //普通函数 { std::cout << "myfunc执行了:tmpvalue = " << tmpvalue << std::endl; } void callObjFunc(std::function<void(int)> cobj) { cobj(120); }
- 调用
callObjFunc(myfunc); callObjFunc([](int tmpvalue) { std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl; });
- 输出
- 通过范例,感受到了std::function的强大能力——接收各种可调用对象并进行实际的调用。
实现类似std::function的功能
- CallFuncObj的类模板,实现std::function的功能
【实现】
//引入一个CFObjHandler类模板,作为可调用对象处理器。 //可调用对象处理器 template <typename T,typename ...Args> class CFObjHandler { public: virtual T invoke(Args... args) const {}; //虚函数,后续要创建子类 }; template <typename U,typename T, typename ...Args> class CFObjHandlerChild :public CFObjHandler<T, Args...> { public: //构造函数 CFObjHandlerChild(U&& tmpfuncobj) :functor(std::forward<U>(tmpfuncobj)) //U&&:使用右值 { } virtual T invoke(Args... args) const //调用可调用对象 { return functor(std::forward<Args>(args)...); }; private: U functor; //U是一个可调用对象类型,functor用于保存可调用对象。 }; //泛化版本(只进行了声明,是因为有特化版本必须得有泛化版本) template <typename T> class CallFuncObj; //特化版本 template <typename T,typename... Args> class CallFuncObj<T(Args...)> //泛化版本中只有一个模板参数,所以这里只有一个模板参数T(Args...) 返回值和参数 //技巧:先看 class CallFuncObj<T(Args...)> 中的参数,再反推template <typename T,typename... Args> { public: //构造函数模板 template <typename U> CallFuncObj(U&& acobj) //可以接收各种可调用对象(函数对象,lambda表达式等) { handler = new CFObjHandlerChild<U, T, Args...>(std::forward<U>(acobj)); } //析构函数 ~CallFuncObj() { delete handler; } public: //重载(),实现该类对象的可调用 T operator()(Args... args) const { return handler->invoke(std::forward<Args>(args)...); //使用了std::forward实现参数的完美转发,保持原始实参的佐治或者右值性。 } private: CFObjHandler<T, Args...>* handler; //可调用对象处理器 }; void callObjFunc2(CallFuncObj<void(int)> cobj) { cobj(120); //会调用CallFuncObj类模板的operator()成员函数 }
- T是可调用对象的返回值类型, Args...是可调用对象的参数类型,U代表是可调用对象的的整体类型。
【调用1】
callObjFunc2(myfunc); callObjFunc2([](int tmpvalue) { std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl; });
- 输出
【调用2】
CallFuncObj<void(int)> f1 = myfunc; f1(1200); CallFuncObj<void(int)> f2 = [](int tmpvalue) { std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl; }; f2(1200); auto ftest = [](int tmpvalue) { std::cout << "lambda表达式执行了,tmpvalue = " << tmpvalue << endl; }; CallFuncObj<void(int)> f3 = ftest; f3(1200);
- 输出