I have a problem using a template with the const keyword (for the type of the function argument), to illustrate it, I created tiny code:
template <typename ClassType, typename ReturnType, typename ... Args>
struct MethodCallerFactory
{
typedef ReturnType (*Type)(ClassType*, Args...);
template <ReturnType (ClassType::*Pointer)(Args...)>
struct Method
{
static Type createMethodCaller()
{
ReturnType (*caller)(ClassType*, Args...) = [](ClassType* obj, Args ... args) -> ReturnType
{
ReturnType (ClassType::*ptr)(Args...) = Pointer;
return (obj->*ptr)(args...);
};
return caller;
}
};
};
class Test
{
public :
void set(const int& p)
{
n = p;
}
void set2(int p)
{
n = p;
}
void set3(const int p)
{
n = p;
}
void set4(int& p)
{
n = p;
}
private :
int n;
};
typedef int& INTREF;
typedef int INTVALUE;
int main()
{
void (*ptr1)(Test*, const int&) = MethodCallerFactory<Test, void, const int&>::Method<&Test::set>::createMethodCaller();
void (*ptr2)(Test*, const INTREF) = MethodCallerFactory<Test, void, const INTREF>::Method<&Test::set>::createMethodCaller();
void (*ptr3)(Test*, int) = MethodCallerFactory<Test, void, int>::Method<&Test::set2>::createMethodCaller();
void (*ptr4)(Test*, INTVALUE) = MethodCallerFactory<Test, void, INTVALUE>::Method<&Test::set2>::createMethodCaller();
void (*ptr5)(Test*, int) = MethodCallerFactory<Test, void, const int>::Method<&Test::set3>::createMethodCaller();
void (*ptr6)(Test*, const INTVALUE) = MethodCallerFactory<Test, void, const INTVALUE>::Method<&Test::set3>::createMethodCaller();
void (*ptr7)(Test*, int&) = MethodCallerFactory<Test, void, int&>::Method<&Test::set4>::createMethodCaller();
void (*ptr8)(Test*, INTREF) = MethodCallerFactory<Test, void, INTREF>::Method<&Test::set4>::createMethodCaller();
}
The only error I get is the declaration of the second pointer:
failed to convert template argument '& Test :: set to' void (Test :: *) (int &) void (ptr2) (Test, const INTREF) = MethodCallerFactory :: Method <& Test :: set> :: createMethodCaller ( );
It seems that when I use typedef with reference types, the compiler forgets the const keyword. I do not understand why there is a problem with this.