Using variable-length parameter templates and lambda (or using generic lambda) to wrap overloaded member function pointers for convenient usage (like bind binding or other places that require overloaded member function pointers). For more introduction on member function pointers, please see my other article: Pointers to Class Members in C++ Are Not Pointers.
Note: The code uses some C++14 features, and you need to compile with the
-std=c++14
parameter.
Currently, there is a class with several overloaded member functions as follows:
1 | struct A |
Typically, we can obtain member function pointers using the following method:
1 | A aobj; |
Since the type system cannot express the candidate set, if we want to bind to this class’s member function func, we can only manually specify the overloaded parameters:
1 | auto x=bind((void(A::*)(float))&A::func,aobj,_1); |
This is too tedious, so we can use a generic lambda
to wrap it:
1 | auto genLambda=[](auto argType)->auto{ |
However, it still feels a bit cumbersome, so let’s make it an auxiliary function where the first template parameter accepts the class type and the second template parameter receives the function’s parameter type:
1 | template<typename T,typename U> |
Then we can call it like this:
1 | // direct call |
Originally, I planned to wrap the bind as well, but using _1
…_n
in the placeholders
namespace becomes inconvenient to specify with different numbers of overloaded function parameters.
Moreover, the code above has a limitation: it can only specify a single parameter function. If I overload multiple parameter versions, the above code won’t work.
However, we can use variable-length parameter templates to support multiple template parameters. Since we must specify at least the class type, there need to be two template parameters, T as the class type and Args as the parameter types of the function members of class A:
1 | template<typename T,typename... Args> |
This way, we can bind multiple parameters. Suppose we have overloaded two versions with multiple parameters on top of the previous class:
1 | struct A |
We can use the variable template parameters version above:
1 | auto AfuncIntFloat=bind(AfuncArgType<A,int,float>(),aobj,_1,_2); |
Compare to the code if done directly:
1 | auto a=bind((void(A::*)(float))&A::func,aobj,_1); |