c++0x: proper way to receive a lambda as parameter by reference

C++LambdaC++11Function PrototypesFunction Parameter

C++ Problem Overview


What is the right way to define a function that receives a int->int lambda parameter by reference?

void f(std::function< int(int) >& lambda);

or

void f(auto& lambda);

I'm not sure the last form is even legal syntax.

Are there other ways to define a lambda parameter?

C++ Solutions


Solution 1 - C++

You cannot have an auto parameter. You basically have two options:

Option #1: Use std::function as you have shown.

Option #2: Use a template parameter:

template<typename F>
void f(F &lambda) { /* ... */}

Option #2 may, in some cases, be more efficient, as it can avoid a potential heap allocation for the embedded lambda function object, but is only possible if f can be placed in a header as a template function. It may also increase compile times and I-cache footprint, as can any template. Note that it may have no effect as well, as if the lambda function object is small enough it may be represented inline in the std::function object.

Solution 2 - C++

I would use template as:

template<typename Functor>
void f(Functor functor)
{
   cout << functor(10) << endl;
}
 
int g(int x)
{
    return x * x;
}
int main() 
{
    auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
    f(lambda); //pass lambda
    f(g);      //pass function 
}

Output:

500
1000
100

Demo : http://www.ideone.com/EayVq

Solution 3 - C++

I know it's been 7 years, but here's a way nobody else mentioned:

void foo(void (*f)(int)){
	std::cout<<"foo"<<std::endl;
	f(1); // calls lambda which takes an int and returns void
}
int main(){
	foo([](int a){std::cout<<"lambda "<<a<<std::endl;});
}

Which outputs:

foo
lambda 1

No need for templates or std::function

Solution 4 - C++

Since C++ 20,

void f(auto& lambda);

actually works (it's an abbreviated function template):

> When placeholder types (either auto or Concept auto) appear in the parameter list of a function declaration or of a function template declaration, the declaration declares a function template, and one invented template parameter for each placeholder is appended to the template parameter list

and it's equivalent to exactly option 2 in @bdonlan's answer:

template<typename F>
void f(F &lambda) { /* ... */}

Solution 5 - C++

> void f(auto& lambda);

That's close. What will actually compile is:

#include <cassert>

/*constexpr optional*/ const auto f = [](auto &&lambda)
{
  lambda();
  lambda();
};

int main()
{
  int counter = 0;
  f([&]{ ++counter; });
  assert(counter == 2);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlurscherView Question on Stackoverflow
Solution 1 - C++bdonlanView Answer on Stackoverflow
Solution 2 - C++NawazView Answer on Stackoverflow
Solution 3 - C++PuddleView Answer on Stackoverflow
Solution 4 - C++Alexey RomanovView Answer on Stackoverflow
Solution 5 - C++Kuba hasn't forgotten MonicaView Answer on Stackoverflow