Lets say I have a variadic higher order function
template<typename F, typename ...Args>
void execution(F func, Args&&... args)
{
func(std::forward<Args>(args)...);
}
Then for this overload set
void f() {}
void f(int arg) {}
Overload resolution will be impossible
int main()
{
execution(f, 1);
execution(f);
return 0;
}
Yet if only either one of the two is provided, the program compiles
If I remove f()
from the set and replace it with f(arg, arg2)
there's still a problem. Is there a workaround, or do I always have to provide the type of the function as a template argument ?
execution<void()>(f);
When doing template type deduction, the compiler doesn't analyse how the types are used inside the function. Therefore when deducing the template parameters, the compiler sees no relation between the different template arguments. Thus the additional variadic template arguments don't matter at all, and the problem can be reduced to
template<typename Func> void execution(Func func);
void f();
void f(int);
execution(f);
With this minimized code, it should be obvious why template argument deduction fails.
You can resolve this by making your first argument explicitly dependent on the remaining template arguments, e.g.:
template<typename... Args>
void execution(void (*func)(Args ...), Args ... args)
{
func(std::forward<Args>(args) ...);
}
You need an overload set object. This is an object that represents the entire overload set of functions of f
:
struct f_overload_set {
template<typename...As>
auto operator()(As&&...as)->
decltype(f(std::declval<As>()...))
{ return f(std::forward<As>(as)...); }
};
now pass f_overload_set{}
to your template
function.
template
s function value arguments must be values, and in current C++ there is no first class value that represents an entire overload set of a function. The symbol f
gets disambiguated into one overload at each point of use: but that requires an immediate context at the point of use. The above defers the disambiguation until we have the arguments handy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With