The problem is that if in the template one of its functional parameters is not a reference type before deduction begins, this parameter will never output to the reference type. Thus, in the output on the left side of T get int , but in the output on the right side of T get int& . This complainer and compiler complain.
It is best to make the function parameter the same type as the function pointer parameter type:
template<typename T> struct identity { typedef T type; }; template<typename T> void f(typename identity<T>::type t, void (*func)(T)) {}
Using identity<T>::type , you turn off the residue on the left side. After determining T on the right side, T lingers on the left side and gives the final parameter type.
One guy suggested taking the right side as a template parameter - this is good, because after that he can overload functional objects with operator() . But you are faced with the problem of knowing if he wants a link or not. To solve this problem, boost has a reference_wrapper (by the way, boost also has an identity template above).
template<typename T, typename F> void f(T t, F func) {}
Now, if you want to pass a link, not a copy, you can do it like this
int i; f(boost::ref(i), some_function);
ref returns a reference_wrapper object that is implicitly converted to T& . Therefore, if you call func(t) , T automatically converted to the target link. If you do not want to pass the link, just pass i directly.