Auto lambda decay for pointer operation when switching to template function

Is there a way to do lambda decay to a pointer without explicitly clicking on the correct signature? This may lead to 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 } 

Obviously, the call call only works if the lambda decays to a pointer, but I assume that this can only happen after choosing the right overload / template function. Unfortunately, I can only think of solutions that include templates to make lambda with any signature decays, so I'll go back to the square.

+7
source share
3 answers

You can change your lambda to use the unary operator + : +[]{ return 0; } +[]{ return 0; }

This works because the unary plus can be applied to pointers and will trigger an implicit conversion to a function pointer.

+13
source

Why don't you unnecessarily limit yourself to pointer functions without default arguments and lambdas without capture, completely eliminating a huge family of functors (for example, std::function , any std::bind results, and everything else that has a suitable operator() )?

Better to simply expand your signature functions:

 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... } 
+1
source

Like a TL; DR; Implementing @Simple's suggestion, I wrote a simple test as follows:

 SCENARIO("decay_equiv", "") { auto callback = +[](struct mosquitto *, void *, const struct mosquitto_message *)->void{}; typedef typename std::is_same< typename std::decay<decltype(callback)>::type, typename std::decay<void (*)(struct mosquitto *, void *, const struct mosquitto_message *)>::type >::type s; std::cout << s::value << std::endl; } 

Try removing + in the callback definition and everything will stop working.

0
source

All Articles