C++14 lambda tutorial
Posted on August 28, 2014 by Paul
The last iteration of C++, C++14 was approved this month. C++14 brings a few much anticipated changes to the C++11 standard, like allowing auto to be used as the return type of a function, or generic lambdas - the subject of this article.
Lambdas, in C++, were introduced by the C++11 standard. They were meant to let the coder write short, anonymous functions, that could be used instead of a function object, avoiding the need to create a separate class and a function definition. Here is a typical example of C++11 lambda usage, that returns the square of a number:
1 int result = [](int input) { return input * input; }(10);
2 cout << result << endl;
If you need to reuse the same piece of code in more than one place, you can save the function in a variable:
1 auto func = [](int input) { return input * input; };
2
3 // first use
4 std::cout << func(10) << std::endl;
5
6 // second use
7 std::cout << func(23) << std::endl;
Can you see the problem with the above code ? It can be used only for integers. What if, we want to use the same lambda for a double or for a complex number ? Say that we want to be able to write something like this:
1 // square of an int
2 std::cout << func(10) << std::endl;
3
4 // square of a double
5 std::cout << func(2.345) << std::endl;
6
7 // square of a complex number
8 std::cout << func(std::complex<double>(3, -2)) << std::endl;
We could obviously use a function template:
1 template <typename T>
2 T func(T z) {
3 return z * z;
4 }
However, this is not the solution we are looking for in the context of this article, the above is a named, global function,
The C++14 standard introduced the concept of generalized lambda, basically we are allowed to use auto for the parameter types of a lambda expression. We could write a shorter and, in a way, more elegant solution now:
1 auto func = [](auto input) { return input * input; };
Here is a complete program that exemplifies the above:
1 #include<iostream>
2 #include<complex>
3
4 int main() {
5 // Store a generalized lambda, that squares a number, in a variable
6 auto func = [](auto input) { return input * input; };
7
8 // Usage examples:
9 // square of an int
10 std::cout << func(10) << std::endl;
11
12 // square of a double
13 std::cout << func(2.345) << std::endl;
14
15 // square of a complex number
16 std::cout << func(std::complex<double>(3, -2)) << std::endl;
17
18 return 0;
19 }
The above code can be compiled with any modern C++ compiler, like GCC 4.9.x or Clang. Here is the result of compiling and running the code with GCC and Clang on OS X:
1 $ clang++ -std=c++1y -pedantic -Wall -stdlib=libc++ test_01.cpp -o test_01
2 $ ./test_01
3 100
4 5.49903
5 (5,-12)
6 $ g++-4.9.1 -std=c++14 -pedantic -Wall test_01.cpp -o test_01
7 $ ./test_01
8 100
9 5.49903
10 (5,-12)
11 $
However, the generic lambda shines in combination with STL. Suppose that you want to sort a vector in decreasing order. Using a generic lambda, we can write:
1 std::sort(V.begin(), V.end(), [](auto i, auto j) { return (i > j); });
Here is a complete example of sorting a vector, of ten integers, in decreasing order, using generic lambda and the STL:
1 #include<iostream>
2 #include<vector>
3 #include<numeric>
4 #include<algorithm>
5
6 int main() {
7 std::vector<int> V(10);
8
9 // Use std::iota to create a sequence of integers 0, 1, ...
10 std::iota(V.begin(), V.end(), 1);
11
12 // Print the unsorted data using std::for_each and a lambda
13 std::cout << "Original data" << std::endl;
14 std::for_each(V.begin(), V.end(), [](auto i) { std::cout << i << " "; });
15 std::cout << std::endl;
16
17 // Sort the data using std::sort and a lambda
18 std::sort(V.begin(), V.end(), [](auto i, auto j) { return (i > j); });
19
20 // Print the sorted data using std::for_each and a lambda
21 std::cout << "Sorted data" << std::endl;
22 std::for_each(V.begin(), V.end(), [](auto i) { std::cout << i << " "; });
23 std::cout << std::endl;
24
25 return 0;
26 }
This is the result of running the above code on my machine:
1 $ g++-4.9.1 -std=c++14 -pedantic -Wall test_02.cpp -o test_02
2 $ ./test_02
3 Original data
4 1 2 3 4 5 6 7 8 9 10
5 Sorted data
6 10 9 8 7 6 5 4 3 2 1
7 $
If you are interested to learn more about the new C++11 syntax I would recommend reading The C++ Programming Language by Bjarne Stroustrup.
or, Professional C++ by M. Gregoire, N. A. Solter, S. J. Kleper: