Lambda Expressions allow users to write an inline expression that can be used for short snippets of code in your C++ app which are not going to be reused and don’t require naming. The Lambda Expression construct is introduced in C++ 11 and further developed in the C++14, C++17, and C++20 standards. In C++14, lambda expressions are improved by the generalized lambda (generic lambda) or initialized lambda feature, and in this post, we remember what lambda is and explain what a generic lambda is, and how we can use it.
Table of Contents
What is a lambda expression in modern C++?
A Lambda Expression defines an anonymous function or a closure at the point where it is used. You can think of a lambda expression as an unnamed function (that’s why it’s called “anonymous”). Lambda expressions help make code cleaner, and more concise and allow you to see behavior inline where it’s defined instead of referring to an external method, like a function. Lambda Expressions are an expression that returns a function object, and they are assignable to a variable whose data type is usually auto and defines a function object. The syntax for a lambda expression consists of specific punctuation with = [ ] ( ) { … } series.
If you are new to lambdas or want to know more about it, please check these two posts that we released before.
How to use a lambda expression in modern C++
Simple Syntax of Lambda Expression is;
1 2 3 |
Datatype Lambda Expression = [Capture Clause] (Parameter List) -> Return Type { Body } |
Now let’s see this syntax in an example. We will define a lambda expression to combine datatypes;
1 2 3 4 5 6 |
int add_integers = []( int a, int b ) { return a + b; }; |
and we can use lambda as below,
1 2 3 |
int x = add_integers( 10, 20 ); |
What is the generic lambda expression in modern C++?
Before C++14, lambda function parameters need to be declared with concrete types, as in the given example above. C++14 has a new generic lambda feature that allows lambda function parameters to be declared with the auto-type specifier.
Generalized lambdas can be defined with the auto keyword that comes with C++11 before. Let’s take the same integer example above, we can define a generic lambda with the auto keyword as below,
1 2 3 4 5 6 |
auto add_things = []( auto a, auto b ) { return a + b; }; |
Generic lambdas are essentially templated functor lambdas. In example, the code above is equivalent to this code,
1 2 3 4 5 6 7 |
struct { template< typename T, typename U > auto operator()( T x, U y ) const { return x + y; } } add_things{}; |
How to use generic lambdas in modern C++
We can use this lambda with int
type,
1 2 3 |
int x = add_things( 10, 20 ); |
or we can use with float
type,
1 2 3 |
float x = add_things( 10.f, 20.f ); |
or we can use it with bool,
char, double
, long long double
,…etc types. This is why it is called as ‘generalized‘, it is a general form that we can use with any types. Very useful and powerful.
Note that, auto
type deduction is added into C++14, and generic lambdas feature follow the rules of template argument deduction.
Is there an example of how to use generic lambdas in modern C++?
Here is a simple example to generic lambdas in modern C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <iostream> int main() { auto lambda = [](auto r) { return r*r; }; // a generic lambda definition int x = 20; int x2 = lambda(x); // using generic lambda std::cout << x2 << std::endl; system("pause"); return 0; } |
Can we use generic lambdas in multi-thread operations?
Multi-thread operations are important and lambda expressions have a lot of advantages in coding and in runtime performance. We can use lambda functions with std::thread that is used for multi-thread runs. Here is a simple example how we can use lambda expression with std::thread
in C++,
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <thread> int main() { auto lambda = [](auto r) { return r*r; }; // a generic lambda definition std::thread myt( lambda, 5 ); // add lambda(5) to thread myt.join(); // join thread to wait the thread execution } |
Here is a paper about this feature, https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html
In C++17, this feature is also handled again, please see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r2.pdf
If you wonder next coming features in C++23, please see Type-generic lambdas https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2738.pdf
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.