Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a lambda to an std::function using templates

Basically, what I want to be able to do is take a lambda with any number of any type of parameters and convert it to an std::function. I've tried the following and neither method works.

std::function([](){});//Complains that std::function is missing template parameters template <typename T> void foo(function<T> f){} foo([](){});//Complains that it cannot find a matching candidate 

The following code does work however, but it is not what I want because it requires explicitly stating the template parameters which does not work for generic code.

std::function<void()>([](){}); 

I've been mucking around with functions and templates all evening and I just can't figure this out, so any help would be much appreciated.

As mentioned in a comment, the reason I'm trying to do this is because I'm trying to implement currying in C++ using variadic templates. Unfortunately, this fails horribly when using lambdas. For example, I can pass a standard function using a function pointer.

template <typename R, typename...A> void foo(R (*f)(A...)) {} void bar() {} int main() {     foo(bar); } 

However, I can't figure out how to pass a lambda to such a variadic function. Why I'm interested in converting a generic lambda into an std::function is because I can do the following, but it ends up requiring that I explicitly state the template parameters to std::function which is what I am trying to avoid.

template <typename R, typename...A> void foo(std::function<R(A...)>) {} int main() {     foo(std::function<void()>([](){})); } 
like image 606
retep998 Avatar asked Nov 13 '12 09:11

retep998


People also ask

Can you template lambda C++?

From the various lambda improvements, template parameters for lambdas are my favorite ones. Lambdas support with C++20 template parameters, can be default-constructed and support copy-assignment, when they have no state, and can be used in unevaluated contexts.

Is a lambda a std :: function?

Lambda's type One important thing to note is that a lambda is not a std::function .

Can std :: function store lambda?

Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

Are functors the same as lambdas?

std::function<int(int,int)>; std::function<void(double)> ... Functors allow to write functional programs in C++. Lambdas are syntactic sugar to simplify this. With functors/lambdas classic patters from functional programming (e.g. map / filter /reduce) can be applied in C++.


1 Answers

You can't pass a lambda function object as an argument of type std::function<T> without explicitly specifying the template argument T. Template type deduction tries to match the type of your lambda function to the std::function<T> which it just can't do in this case - these types are not the same. Template type deduction doesn't consider conversions between types.

It is possible if you can give it some other way to deduce the type. You can do this by wrapping the function argument in an identity type so that it doesn't fail on trying to match the lambda to std::function (because dependent types are just ignored by type deduction) and giving some other arguments.

template <typename T> struct identity {   typedef T type; };  template <typename... T> void func(typename identity<std::function<void(T...)>>::type f, T... values) {   f(values...); }  int main() {   func([](int x, int y, int z) { std::cout << (x*y*z) << std::endl; }, 3, 6, 8);   return 0; } 

This is obviously not useful in your situation though because you don't want to pass the values until later.

Since you don't want to specify the template parameters, nor do you want to pass other arguments from which the template parameters can be deduced, the compiler won't be able to deduce the type of your std::function argument.

like image 130
Joseph Mansfield Avatar answered Sep 29 '22 21:09

Joseph Mansfield