I am having some troubles understanding why the following code cannot compile
#include <iostream>
#include <typeinfo>
#define PRINT_FUNC() {std::cout << __PRETTY_FUNCTION__ << std::endl;}
struct Obj {
Obj(){PRINT_FUNC();}
int run (float f, char *c) {
PRINT_FUNC();
return 0;
}
int fly () {
PRINT_FUNC();
return 0;
}
};
template <typename OBJ, typename R, typename ... Args>
void call_obj_func (OBJ &&o, R(OBJ::*fn)(Args...), Args ... args) {
PRINT_FUNC();
(o.*fn)(args...);
}
int main () {
Obj o;
call_obj_func(o, &Obj::fly);
}
For the function call_obj_func I expected the type of OBJ to be used for BOTH rvlaue and lvalue types. However when calling with a lvalue type, the compiler complains that there is ambuigity of using the types: Obj and Obj&
This means that the comiler isnt sure wheter to use a copy of the obj or the reference to the obj.
I am sure there is some syntax error as I would like the function call_obj_func to be compiled with both lvalue and rvalue types.
My assumption is the member function pointer as the syntax (Obj&::*fn) and (Obj::*fn) might have different semantics. (Though I cannot find the differences anywhere).
You may write
template <typename OBJ, typename Method, typename ... Args>
void call_obj_func (OBJ &&o, const Method& fn, Args&& ... args) {
PRINT_FUNC();
(std::forward<OBJ>(o).*fn)(std::forward<Args>(args)...);
}
As currently, you have conflict with type deduction (Obj&
vs Obj
, and you may have similar issues with args
)