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: