C++11 Tidbits: Lambda Expressions (Part 2)

Previously I briefly introduced Lambda expressions. To show some more examples, consider the following:

  std::cout << [](float f) { return std::abs(f); } (-3.5);

The output is, of course, "3.5", because the function object is applied to the argument -3.5 and returns 3.5 as the value computed by std::abs. The return type is automatically deduced to be a float but could also be explicitly specified:

  std::cout << [](float f) -> int { return std::abs(f); } (-3.5);	      

What happens here is that the float 3.5 is truncated to the integer 3. The return type can also be preceded by an exception specification with the exact same meaning as in function declarations (this will be a good topic for a future tidbit because C++1x has interesting news in this area).

The open/closed squared brackets which introduce a lambda are called in jargon the lambda-introducer. Many forms of it are possible adding a lot of flexibility. For example:

  float f0 = 1.0;
  std::cout << [=](float f) { return f0 + std::abs(f); } (-3.5);

outputs "4.5". The equal sign enables the lambda to capture - also a term of art - all the automatic variables in scope by value. Changing the example to

  float f0 = 1.0;
  std::cout << [&](float f) { return f0 += std::abs(f); } (-3.5);
  std::cout << '\n' << f0 << '\n';

outputs "4.5", followed on the next line by "4.5". The ampersand lambda-introducer indicates all the automatic variables are captured by reference. Compare it to this variant:

  float f0 = 1.0;
  std::cout << [=](float f) mutable { return f0 += std::abs(f); } (-3.5);
  std::cout << '\n' << f0 << '\n';

where the automatic variables in scope are captured by value as in the first example but can be also modified in the lambda body, which is not normally the case for variables captured by value and would otherwise give a compilation error. This example outputs "4.5" followed by "1.0".

All the above capture syntaxes establish only the default: the code can specify different modes for individual variables. For example:

  float f0 = 1.0f;
  float f1 = 10.0f;
  std::cout << [=, &f0](float a) { return f0 += f1 + std::abs(a); } (-3.5);
  std::cout << '\n' << f0 << '\n';

outputs "14.5" followed again by "14.5" on the next line. In this case f0 is captured by reference while all the other automatics, i.e. f1, are captured by value.

The gist of the various available syntaxes should be clear enough by now. As always, the web is a precious resource for many more. Experimenting with lambdas together with std::sort, std::for_each and the other numeric facilities in the standard library is also highly recommended.

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

C++ enthusiasts only, please! ;)

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today