A C++11 template function which takes a function object argument, such as:
template <typename F, typename T>
auto foo(F f, T x) -> decltype(f(x)) {
return f(x);
}
could take a function such as:
int succ(int i) { return i+1; }
and apply foo to succ and obtain a result of 10:
foo(succ,9);
Overloaded functions don’t work, sin, for example, fails:
foo(std::sin,0.5);
in GCC (4.7) with “couldn’t deduce template parameter F”.
(Providing sin<double> relates only to complex types btw.) Yes, I can struct it right up:
template <typename T>
struct Sin {
T operator()(T x) { return std::sin(x); }
};
with a little:
foo(Sin<double>(),0.5);
My question is, is there an alternative which avoids the need for such a new definition; usable solely at the call site of foo?
For function pointers, you can simply have the user type the signature:
Live example on Ideone.
foowill bevoid foo(void f(int), int x)after substitution, which is the same asfoo(void (*f)(int), int x). This provides a so-called “calling context” which allows the compiler to select the correct overload. Obviously, this only works well if the first template parameter is the function. To work around this limitation, and make it look nicer (imho, atleast), you can provide a simple helper function:Actually, you can only overload on parameter types, but this you can’t cull out the need to have the user type the return type, since this disables the calling context again, as a type would need to be deduced.
Since you most likely (or surely) only want this for function pointers, you can change it to this:
It’s still completely the same. The only reason why the first version can’t just have
Fas the return type is thatFisvoid(int)if you call it withget_overload<void(int)>(bar), and the standard doesn’t allow you to return functions (yes, that’s a function type). The function to function pointer transformation (void(int)->void(*)(int)) part only happens for parameters.Since for whatever reason @VJovic deleted his answer, I’ll just edit this in:
You can actually use a simple lambda instead of the
get_overloadfunction. It will be about the same length character wise and much more convenient and clearer. It will also be more efficient, since no (function) pointers are involved and the compiler is perfectly able to inline the call.