Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

explicit call to variadic function template with empty parameter pack

Consider this simple (bad) function template for which lots of variations exist on this site:

template <typename R, typename... Args>
R call_with(std::function<R(Args...)> f,
            Args... args)
{
    return f(args...);
}

And two attempts at calling it:

call_with([]{});        // (a)
call_with<void>([]{});  // (b)

I cannot call (a) because a lambda is not a std::function<R(Args...)> so template deduction fails. Straightforward.

However, (b) also fails. I suspect this is because the compiler cannot determine that I mean to provide all the type arguments and reasons that I am simply providing R - so it is trying (and failing) to deduce Args... for the same reason that the initial call failed.

Is there a way to explicitly specify that I am providing all the template arguments? To clarify, I am interested only in how to explicitly provide the template arguments so that there is no template deduction - I am not looking for the correct way to write call_with or for a way to make template deduction succeed when called with a lambda.

like image 314
Barry Avatar asked Jul 15 '15 20:07

Barry


1 Answers

You could specify the function type beforehand, like this:

int main(){
    std::function<void()> f = []{};
    call_with(f);
}

or, in a little more messy but more compact way:

int main(){
    call_with(static_cast<std::function<void()>>([]{}));
}

This is because the compiler doesn't know what return type and arguments to deduce for your template parameters before you ask it to implicitly convert a lambda, which is an unspecified function object defined by the compiler, to a std::function with those template parameters.

Really, you should just change your function warpper to be more generic:

template<typename Functor, typename ... Args>
auto wrapper(Functor &&f, Args &&... args) -> decltype(f(std::forward<Args>(args)...)){
    return f(std::forward<Args>(args)...);
}

This should work for any function or functor type. It's also a really good example of the use of trailing return types.

Here's a live example

like image 56
RamblingMad Avatar answered Nov 15 '22 20:11

RamblingMad