使用变长参数模板和lambda(或者使用generic lambda)来裹一层重载的成员函数指针,从而方便使用(bind绑定或者其他需要重载的成员函数指针的地方)。
关于成员函数指针的更多介绍请看我的另一篇文章:C++中指向类成员的指针并非指针。
注意:代码有些用到了C++14的特性,编译时需加上
-std=c++14
参数。
当前有一个类,重载了几个成员函数,如下:
1 | struct A |
通常我们可以使用下面的方法得到成员函数指针:
1 | A aobj; |
由于类型系统不能表示candidate set,如果我们想要bind到这个类的成员函数func,只能手动指定重载的参数:
1 | auto x=bind((void(A::*)(float))&A::func,aobj,_1); |
这样太麻烦了,可以使用generic lambda
来裹一下:
1 | auto genLambda=[](auto argType)->auto{ |
但是感觉还是有点繁琐,干脆做成一个辅助函数,第一个模板参数接受类类型,第二个模板参数接收函数的参数类型:
1 | template<typename T,typename U> |
然后就可以这样调用:
1 | // direct call |
本来打算把bind的也裹进去,但是在placeholders
名字空间中的_1
…_n
这些在重载的函数参数个数不同时就不方便指定了。
而且上面的代码还有一个局限性:只能指定一个参数的函数,如果我重载了多个参数的版本,则上面的代码是行不通的。
但是我们使用可变参数模板可以实现支持多个模板参数,因为至少要指定类类型,所以要有两个模板参数,T作为类类型,Args作为A类的函数成员的参数类型:
1 | template<typename T,typename... Args> |
这样我们就可以绑定多个参数了,假如我们在之前的类的基础上又重载了两个多参数的版本:
1 | struct A |
我们可以使用上面可变模板参数的版本:
1 | auto AfuncIntFloat=bind(AfuncArgType<A,int,float>(),aobj,_1,_2); |
对比一下如果直接硬怼的代码:
1 | auto a=bind((void(A::*)(float))&A::func,aobj,_1); |