Solarian Programmer

My programming ramblings

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:


Show Comments