I’m trying to understand function forwarding with lambdas on C++ by running this code:
#include <functional>
template<typename Func, typename... Args>
int do_something_1(int foo_1, Func&& func, Args&&... args, int foo_0 = 0) {
int var_1 = foo_0 + 2 * foo_1;
return std::forward<Func>(func)(var_1, std::forward<Args>(args)...);
};
int main (void) {
return do_something_1(1, [](int var_1, int local_var) { return (var_1 + local_var); }, 4);
}
However it fails with this compilation error:
<source>: In instantiation of 'int do_something_1(int, Func&&, Args&& ..., int) [with Func = main()::<lambda(int, int)>; Args = {}]':
<source>:11:93: required from here
<source>:7:36: error: no match for call to '(main()::<lambda(int, int)>) (int&)'
7 | return std::forward<Func>(func)(var_1, std::forward<Args>(args)...);
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:7:36: note: candidate: 'int (*)(int, int)' (conversion)
<source>:7:36: note: candidate expects 3 arguments, 2 provided
<source>:11:30: note: candidate: 'main()::<lambda(int, int)>'
11 | return do_something_1(1, [](int var_1, int local_var) { return (var_1 + local_var); }, 4);
| ^
<source>:11:30: note: candidate expects 2 arguments, 1 provided
And I don’t know how to correct it.
>Solution :
Non-terminal function parameter packs are a "non-deduced context" ([temp.deduct.type]/5):
The non-deduced contexts are:
- […]
- A function parameter pack that does not occur at the end of the parameter-declaration-list.
This means that the 4
which you pass as an argument will not be used to deduce Args
, but is instead bound to foo_0
.
Technically you can make this compile by providing template arguments explicitly:
int main (void) {
return do_something_1<int(*)(int,int), int>(1, [](int var_1, int local_var) { return (var_1 + local_var); }, 4);
}
This works because the non-capturing lambda can convert to a function pointer, and explicitly supplying int
as a second template argument causes the 4
to bind to args...
instead of foo_0
.
But in general I’d recommend avoiding non-terminal function parameter packs when possible.