C++11绑定器bind及function机制( 六 )

function对象接收hello函数时,R作为返回值会被推导为voidA1作为单一参数类型被推导为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推导为intA1sum的第一个参数类型intA2sum的第二个类型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 = &sum;// 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之前的bind1stbind2nd引入,介绍了C++11的bind的使用 , 理清了它的作用,何谓“绑定”?然后介绍了function的使用方法,并对其进行了逻辑上的实现,以上这些知识点都挺难的,涉及函数对象、模板特化、可变参数模板 。但是也算是一次系统性总结吧,感觉意义蛮大的 。C++11的路还很远,以后有机会再继续深耕吧 。
顺便记录一下,我还在为自己的秋招迷茫中,如果有好消息,我在回来还愿!
【C++11绑定器bind及function机制】

推荐阅读