Is there a way to make a lambda decay to a pointer, without explicitly casting to the right signature? This would tidy some code:
template<typename T> T call(T(*func)()){ return func(); }
int ptr(){ return 0; }
int main(){
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; }));
auto ret3 = call([]{ return 0; }); //won't compile
}
It's evident that a call to call
works only if the lambda decays to a pointer, but I'm guessing that that can happen only after the right function overload/template is chosen. Unfortunately I can only think of solutions that involve templates to make a lambda with any signature decay, so I'm back to square one.
A lambda expression with an empty capture clause is convertible to a function pointer. It can replace a stand-alone or static member function as a callback function pointer argument to C API.
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.
You often use functors instead - that is, classes that overload the operator () , so that they can be "called" as if they were functions. Functors have a couple of big advantages over function pointers: They offer more flexibility: they're full-fledged classes, with constructor, destructor and member variables.
You can change your lambda to use the unary +
operator: +[]{ return 0; }
This works because unary plus can be applied to pointers, and will trigger the implicit conversion to function pointer.
Why would you unnecessarily constrain yourself to function pointers without defaulted arguments and lambdas without captures, completely ruling out the huge family of functors (e.g. std::function
, any results of std::bind
and everything else that has a suitable operator()
)?
Better just broaden your function signature:
template <typename F>
auto call(F func) -> decltype(func()) {
return func();
}
int ptr() { return 0; }
int g(int i = 0) {return i;}
int main() {
auto ret1 = call(ptr);
auto ret2 = call((int(*)())([]{ return 0; })); //tedious, but works
auto ret3 = call([]{ return 0; }); //ok now.
auto ret4 = call(g); //ok now!
int i = 42;
auto ret5 = call([=]{return i;}); //works, too!
auto ret6 = call(std::bind(g, i)); //and so on...
}
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