The Lambda Expression construct is introduced in C++ 11 and further developed in the C++14, C++17, and C++20 standards. C++14 standard introduced the generalized lambda capture (init capture) that allows you to specify generalized captures, it allows to use move capture in lambdas. In C++14, lambda expressions are improved by the generalized lambda (generic lambda) and by this generalized lambda captures. In this post, we explain how to use generalized lambda captures in modern C++
Table of Contents
What is a lambda in 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 them, please check these two posts that we released before.
- The step-by-step guide to lambda expressions in a C++ app
- Advantages and disadvantages of the c programming language
How to use a generalized lambda function in 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.
The basic syntax of a Lambda Expression in C++ is;
1 2 3 |
Datatype Lambda Expression = [Capture Clause] (Parameter List) -> Return Type { Body } |
Generalized lambdas can be defined with the auto
keyword that comes with C++11. 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; }; |
We can use this lambda with an int
type,
1 2 3 |
int x = add_things( 10, 20 ); |
or we can use it with a float
type,
1 2 3 |
float f = 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.
What are generalized lambda captures in C++?
The Lambda Expression construct is introduced in C++ 11 and further developed in the C++14, C++17, and C++20 standards. C++14 standard introduced the generalized lambda capture (also known as init capture) that allows you to specify generalized captures. In C++14, lambda expressions are improved by the generalized lambda (generic lambda) and by this generalized lambda captures, it allows to use move capture in lambdas.
A generalized capture is a new and more general capture mechanism, it allows us to specify the name of a data member in the closure class generated from the lambda, and an expression initializing that data member. Lambdas can capture expressions, rather than just variables as in functions, and this feature allows lambdas to store move-only types.
How to use generalized lambda captures in C++
Let’s see how we can use generalized lambda captures in modern C++,
std::move can be used to move objects in lambda captures as below,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
struct st_xy { int x, y; } xy; int main() { auto lambda3 = [ r = std::move(xy)]() { return r; }; } |
generalized lambda can be a mutable generator as we show below.
1 2 3 4 5 6 7 8 9 |
auto iterator = [iter = 0] () mutable { return iter++; }; auto i0 = iterator(); auto i1 = iterator(); |
we can use function in generalized lambdas,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> #include <memory> int myf(int r) { return r*r; } int main() { auto f = [x = myf(8)] { return x; }; } |
Here is a paper about this feature, https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3648.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.