当function对象接收hello函数时,R作为返回值会被推导为void,A1作为单一参数类型被推导为string类型:
myfunction<void(string)> f1 = &hello;f1("hello world");//打印"hello world"那现在如果我们要接收两个参数的sum求和函数呢?
int sum(int a, int b) { return a + b; }其实理解了function的原理后,这个时候要接收一个双参数sum求和函数,可以再去特化一个适合sum的类 , 其中R推导为int,A1为sum的第一个参数类型int,A2为sum的第二个类型int:
#include <iostream>using namespace std;int sum(int a, int b) { return a + b; }template<typename T>class myfunction {};//两个类型参数模板完全特例化template<typename R, typename A1, typename A2>class myfunction<R(A1, A2)> {public:using PFUNC = R (*)(A1, A2);public:myfunction(PFUNC pfunc) : _pfunc(pfunc) {}R operator()(A1 arg1, A2 arg2) {return _pfunc(arg1, arg2);}private:PFUNC _pfunc;};int main() {myfunction<int(int, int)> f2 = ∑// myfunction<int(int, int)> f2(&sum);cout << f2(3, 4) << endl;// 输出5return 0;}以上就是function去接收单参数和双参数时的实现,但是这有个很致命的缺点,如果要接收三个参数、四个参数、十个参数、一百个参数、一千个参数呢?(当然这不太可能 , 就是单纯去考虑这种情况),那是不是还得对不同参数都进行一次实现?那模板的意义何在?如何消除代码冗余就是问题所在,我们需要用到可变模板参数,我的这篇文章已经说明什么是可变参数模板,如何去使用它:[ 泛化之美 —— C++11 可变参数模板的妙用 ]
所以通过可变模板参数,我们去实现一个可变参数的function,该function可以接收任意数量参数的函数、函数对象、lambda表达式、bind适配后的成员函数和普通函数等等:
template<typename T>class myfunction {};/*那如果类型参数多了,我们还要一个一个定义吗??其实可以采用变长参数模板实现*/// 可变参数模板完全特例化template<typename R, typename... A>class myfunction<R(A...)> {public:using PFUNC = R (*)(A...);public:myfunction(PFUNC pfunc) : _pfunc(pfunc) {}R operator()(A... arg) {return _pfunc(arg...);}private:PFUNC _pfunc;};根据以上实现,我们对function的底层原理有了深刻的认识,能够自己实现一个接收任意参数的function模板类 。虽然以上实现和标准库还差得很远,但是起到了学习、理解的作用吧 。
总结本文通过C++11之前的bind1st和bind2nd引入,介绍了C++11的bind的使用 , 理清了它的作用,何谓“绑定”?然后介绍了function的使用方法,并对其进行了逻辑上的实现,以上这些知识点都挺难的,涉及函数对象、模板特化、可变参数模板 。但是也算是一次系统性总结吧,感觉意义蛮大的 。C++11的路还很远,以后有机会再继续深耕吧 。
顺便记录一下,我还在为自己的秋招迷茫中,如果有好消息,我在回来还愿!
【C++11绑定器bind及function机制】
推荐阅读
- .net core Blazor+自定义日志提供器实现实时日志查看器
- 小样本利器4. 正则化+数据增强 Mixup Family代码实现
- 学习ASP.NET Core Blazor编程系列九——服务器端校验
- nginx 客户端返回499的错误码
- 三、Go环境安装
- 100版本dnf如何给武器镶嵌徽章(dnf如何在装备上镶嵌徽章)
- oppoa93参数配置详情_oppoa93参数配置详情处理器
- 崩坏3武器索尔之锤强度如何
- 天玑1100相当于骁龙多少处理器_天玑1100相当于骁龙什么水平
- 我的世界暗物质武器怎么做(我的世界暗物质套怎么合成)
