I want to be able to obtain a function pointer to a lambda in C++.
I can do:
int (*c)(int) = [](int i) { return i; };
And, of course, the following works - even if it's not creating a function pointer.
auto a = [](int i) { return i; };
But the following:
auto *b = [](int i) { return i; };
Gives this error in GCC:
main.cpp: In function 'int main()': main.cpp:13:37: error: unable to deduce 'auto*' from '<lambda closure object>main()::<lambda(int)>{}' auto *b = [](int i) { return i; }; ^ main.cpp:13:37: note: mismatched types 'auto*' and 'main()::<lambda(int)>'
It seems arbitrary that a lambda can be converted to a function pointer without issue, but the compiler cannot infer the function type and create a pointer to it using auto *
. Especially when it can implicitly convert a unique, lambda type
to a function pointer:
int (*g)(int) = a;
I've create a little test bed at http://coliru.stacked-crooked.com/a/2cbd62c8179dc61b that contains the above examples. This behavior is the same under C++11 and C++14.
C++ Lambdas Conversion to function pointer This feature is mainly useful for using lambdas with APIs that deal in function pointers, rather than C++ function objects. Conversion to a function pointer is also possible for generic lambdas with an empty capture list.
The type of a lambda expression is unspecified. But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor.
This fails:
auto *b = [](int i) { return i; };
because the lambda is not a pointer. auto
does not allow for conversions. Even though the lambda is convertible to something that is a pointer, that's not going to be done for you - you have to do it yourself. Whether with a cast:
auto *c = static_cast<int(*)(int)>([](int i){return i;});
Or with some sorcery:
auto *d = +[](int i) { return i; };
Especially when it can implicitly convert a unique, lambda type to a function pointer:
But it cannot convert it to "a function pointer". It can only convert it to a pointer to a specific function signature. This will fail:
int (*h)(float) = a;
Why does that fail? Because there is no valid implicit conversion from a
to h
here.
The conversion for lambdas is not compiler magic. The standard simply says that the lambda closure type, for non-capturing, non-generic lambdas, has an implicit conversion operator for function pointers matching the signature of its operator()
overload. The rules for initializing int (*g)(int)
from a
permit using implicit conversions, and thus the compiler will invoke that operator.
auto
doesn't permit using implicit conversion operators; it takes the type as-is (removing references, of course). auto*
doesn't do implicit conversions either. So why would it invoke an implicit conversion for a lambda closure and not for a user-defined type?
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