Consider the following:
#include <utility>
#include <string>
template<typename>
class C;
template<typename R, typename T>
class C<R(&)(T)> {
public:
template<typename F>
C(F&& fun) {}
};
template<typename T>
C<T> makeC(T&& fun) {
return C<T>(std::forward<T>(fun));
}
int foo(int a){return a;}
int main() {
auto p1 = makeC(foo); // OK
auto p2 = C<int(&)(int)>([](int a){return a;}); // OK
// auto p3 = makeC([](int a){return a;}); // FAIL
}
The declaration of p3 fails because the compiler can't infer the type int(&)(int) from the lambda that was passed as parameter. p1 is ok because the type can be easily infered from the function foo, and p2 is ok because the type is explicitly declared.
It fails with:
error: invalid use of incomplete type 'class C<main()::<lambda(int)> >'
Is there any way to make the compiler infer the function type corretly, given a lambda?
P.S.: C++17 answers are also ok, if applicable.
The actual problem is that a lambda function has it own type, that cannot be reduced to
R(&)(T). Because of that,C<T>is an incomplete type as correctly outlined by the compiler.As long as you use non-capturing lambdas, you can rely on the fact that they decay to function pointers and do this:
Or this:
Another possible solution that works with capturing lambdas is this:
This way, when dealing with a lambda,
Cactually inherits from it and privately contains itsoperator().