The problem is that if in a template one of its function parameters is not a reference type before deduction starts, that parameter will never deduce to a reference type. So in the deduction on the left side, T
yields int
, but on the deduction on the right side, T
yields int&
. That's a mistmatch and the compiler complains.
The best is to make the function parameter the same type as the parameter type of the function pointer:
template<typename T> struct identity { typedef T type; };
template<typename T>
void f(typename identity<T>::type t, void (*func)(T)) {}
By using identity<T>::type
, you disable deduction on the left side. Once the T
was determined at the right side, T
is sustituted into the left side and yields the final parameter type.
One guy proposed to take the right side as a template parameter - this is a good thing since it can then accept function objects with operator()
overloaded. But you then face the problem of having to know whether it wants a reference or not. To solve it, boost
has reference_wrapper
(by the way, boost
also has the identity
template above).
template<typename T, typename F>
void f(T t, F func) {}
Now, if you want to pass a reference and not a copy, you can do that like this
int i;
f(boost::ref(i), some_function);
ref
returns a reference_wrapper object which is implicitly convertible to T&
. So if you call func(t)
, the t
is converted to the target reference automagically. If you don't want to pass a reference, just pass i
directly.