什么是 lambda 表达式?何时应该使用它?
C++11 中的 lambda 表达式是什么?我什么时候会使用一个?他们解决了哪些在引入之前无法解决的问题?
一些示例和用例会很有用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
C++11 中的 lambda 表达式是什么?我什么时候会使用一个?他们解决了哪些在引入之前无法解决的问题?
一些示例和用例会很有用。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(11)
解答
问:C++11 中什么是 lambda 表达式?
答:在底层,它是一个自动生成的类的对象,带有重载的operator() const。这样的对象称为闭包,由编译器创建。
这种“闭包”概念类似于 C++11 中的“绑定”概念,但 lambda 通常会生成性能更高的代码。此外,通过闭包(而不是典型函数)的调用允许完全内联。
问:我什么时候会使用一个?
答:当你想定义“简单而小的逻辑”并要求编译器根据上一个问题执行生成时。您为编译器提供了一些您希望位于
operator()
内的表达式。所有其他的东西,编译器都会为你生成。问: lambda 解决了哪些在引入之前无法解决的问题?
答:Lambda 更像是一种语法糖(即易于使用的代码),例如“运算符重载”,而不必为自定义加、减操作创建整个函数... Lambda节省更多行不需要的代码,将 1-3 行实际逻辑包装到某些类中,等等!一些工程师认为如果行数越少,出错的机会就越小(我也这么认为)。
使用示例
有关 lambda 的附加内容,问题未涵盖。如果您不感兴趣,请忽略此部分
1.捕获的值。您可以捕获什么
1.1。您可以在 lambda 中引用具有
static
存储持续时间的变量。他们都被俘虏了。1.2.您可以使用 lambda “按值”捕获值。在这种情况下,捕获的变量将被复制到函数对象(闭包)。
1.3.您可以通过引用捕获。 & -- 在这种情况下意味着引用,而不是指针。
1.4.存在符号可以按值或参考
1.5 捕获所有非静态变量。存在符号可以按值或按引用捕获所有非静态变量,同时将特定变量重写为专门按值或按引用
示例:
按值捕获所有非静态变量,但按引用捕获 Param2
按引用捕获所有非静态变量,但按值捕获 Param2
2。返回类型推导
2.1.如果 lambda 是一个表达式,则可以推导出 Lambda 返回类型。或者您可以明确指定它。
如果 lambda 有多个表达式,则必须通过尾随返回类型指定返回类型。
此外,类似的语法可以应用于自动函数和成员函数
3。捕获的值。你无法捕捉到的东西
3.1。您只能捕获局部变量,而不能捕获对象的成员变量。
4。转换
4.1! Lambda 不是函数指针,也不是匿名函数,但是无捕获 lambda 可以隐式转换为函数指针。
Ps
更多关于 lambda 语法的信息可以在Programming Language C++ #337, 2012-01-16, 5.1.2 中找到。 Lambda 表达式,第 88 页
在 C++14 中,添加了一个名为“init capture”的额外功能。它允许您任意执行闭包数据成员的声明:
Answers
Q: What is a lambda expression in C++11?
A: Under the hood, it is the object of an autogenerated class with an overloaded operator() const. Such an object is called a closure and is created by the compiler.
This 'closure' concept is similar to the 'bind' concept from C++11, but lambdas typically generate more performant code. Also, calls through closures (instead of typical functions) allow full inlining.
Q: When would I use one?
A: When you want to define "simple and small logic" and ask the compiler to perform generation from previous question. You give a compiler some expressions which you want to be inside
operator()
. All the other stuff, the compiler will generate for you.Q: What class of problem do lambdas solve that wasn't possible to solve prior to their introduction?
A: Lambdas are more of a syntactical sugar (i.e., code meant for ease-of-use) like "operator overloading" instead of having to make entire functions for custom add, subtract operations... Lambdas save more lines of unneeded code to wrap 1-3 lines of real logic to some classes, and etc.! Some engineers think that if the number of lines is smaller, then there is a lesser chance to make errors in it (I'm think so too).
Example of usage
Extras about lambdas, not covered by question. Ignore this section if you're not interested
1. Captured values. What you can capture
1.1. You can reference to a variable with
static
storage duration in lambdas. They all are captured.1.2. You can use lambda to capture values "by value". In such case, captured vars will be copied to the function object (closure).
1.3. You can capture by reference. & -- in this context mean reference, not pointers.
1.4. Notation exists to capture all non-static vars by value, or by reference
1.5. Notation exists to capture all non-static vars by value, or by reference, while overriding specific variables to be specifically by-value or by-reference
Examples:
Capture all not-static vars by value, but by reference capture Param2
Capture all not-static vars by reference, but by value capture Param2
2. Return type deduction
2.1. Lambda return type can be deduced if lambda is one expression. Or you can explicitly specify it.
If lambda has more than one expression, then return type must be specified via trailing return type.
Also, similar syntax can be applied to auto functions and member-functions
3. Captured values. What you cannot capture
3.1. You can capture only local vars, not member variables of the object.
4. Сonversions
4.1 !! Lambda is not a function pointer and it is not an anonymous function, but capture-less lambdas can be implicitly converted to a function pointer.
P.s.
More about lambda grammar information can be found in Working draft for Programming Language C++ #337, 2012-01-16, 5.1.2. Lambda Expressions, p.88
In C++14 an extra feature, named as "init capture", has been added. It allows you to arbitrarily perform declaration of closure data members:
lambda 函数是您内联创建的匿名函数。正如一些人所解释的那样,它可以捕获变量(例如 http://www.stroustrup.com/C++11FAQ .html#lambda),但有一些限制。例如,如果有这样的回调接口,
您可以当场编写一个函数来使用它,就像下面传递给 apply 的函数一样:
但您不能这样做:
因为 C++11 标准的限制。如果你想使用捕获,你必须依赖库和
(或其他一些STL库,比如间接获取它的算法),然后使用std::function,而不是像这样传递普通函数作为参数:
A lambda function is an anonymous function that you create in-line. It can capture variables as some have explained, (e.g. http://www.stroustrup.com/C++11FAQ.html#lambda) but there are some limitations. For example, if there's a callback interface like this,
you can write a function on the spot to use it like the one passed to apply below:
But you can't do this:
because of limitations in the C++11 standard. If you want to use captures, you have to rely on the library and
(or some other STL library like algorithm to get it indirectly) and then work with std::function instead of passing normal functions as parameters like this:
C++ 作者 Bjarne Stroustrup 在他的书
***C++ 编程语言***
中给出了lambda 表达式
的最佳解释之一。第 11 章 (ISBN-13: 978-0321563842):什么是 lambda 表达式?
我什么时候会使用它?
他们解决了什么类型的问题,而这些问题在引入之前是不可能的?
在这里,我想使用 lambda 表达式完成的每个操作都可以在没有它们的情况下解决,但还有更多代码和更大的复杂性。 Lambda 表达式这是优化代码的方式,也是使其更具吸引力的方式。正如斯特劳斯特普所说的悲伤:
优化
一些示例
通过 lambda 表达式
或函数
,或者即使
您需要,您也可以命名
lambda 表达式
,如下所示:或者假设另一个简单的 样本
接下来将生成
[]
- 这是捕获列表或lambda 引入器
:如果lambda
不需要访问其本地环境,我们可以使用它。引自书中:
其他
Lambda表达式
格式其他参考:
One of the best explanation of
lambda expression
is given from author of C++ Bjarne Stroustrup in his book***The C++ Programming Language***
chapter 11 (ISBN-13: 978-0321563842):What is a lambda expression?
When would I use one?
What class of problem do they solve that wasn't possible prior to their introduction?
Here i guess every action done with lambda expression can be solved without them, but with much more code and much bigger complexity. Lambda expression this is the way of optimization for your code and a way of making it more attractive. As sad by Stroustup :
Some examples
via lambda expression
or via function
or even
if u need u can name
lambda expression
like below:Or assume another simple sample
will generate next
[]
- this is capture list orlambda introducer
: iflambdas
require no access to their local environment we can use it.Quote from book:
Additional
Lambda expression
formatAdditional references:
C++ 中的 lambda 被视为“即时可用函数”。
是的,它确实是在旅途中,您可以定义它;使用它;当父函数作用域结束时,lambda 函数就消失了。
c++ 在 c++ 11 中引入了它,每个人都开始在每个可能的地方使用它。
示例以及什么是 lambda 可以在这里找到 https://en.cppreference.com/w /cpp/language/lambda
我将描述哪些内容不存在,但对于每个 C++ 程序员来说都是必不可少的
Lambda 并不意味着可以在任何地方使用,并且每个函数都不能使用替换为 lambda。与正常功能相比,它也不是最快的。因为它有一些开销需要由 lambda 来处理。
在某些情况下,它肯定有助于减少行数。
它基本上可以用于在同一函数中被调用一次或多次的代码部分,并且其他地方不需要该代码段,因此您可以为其创建独立函数。
下面是 lambda 的基本示例以及后台发生的情况。
用户代码:
编译如何扩展它:
如您所见,当您使用它时它会增加什么样的开销。
所以到处使用它们并不是一个好主意。
可以用在适合的地方。
The lambda's in c++ are treated as "on the go available function".
yes its literally on the go, you define it; use it; and as the parent function scope finishes the lambda function is gone.
c++ introduced it in c++ 11 and everyone started using it like at every possible place.
the example and what is lambda can be find here https://en.cppreference.com/w/cpp/language/lambda
i will describe which is not there but essential to know for every c++ programmer
Lambda is not meant to use everywhere and every function cannot be replaced with lambda. It's also not the fastest one compare to normal function. because it has some overhead which need to be handled by lambda.
it will surely help in reducing number of lines in some cases.
it can be basically used for the section of code, which is getting called in same function one or more time and that piece of code is not needed anywhere else so that you can create standalone function for it.
Below is the basic example of lambda and what happens in background.
User code:
How compile expands it:
so as you can see, what kind of overhead it adds when you use it.
so its not good idea to use them everywhere.
it can be used at places where they are applicable.
嗯,我发现的一个实际用途是减少样板代码。例如:
如果没有 lambda,您可能需要针对不同的
bsize
情况执行某些操作。当然你可以创建一个函数,但是如果你想将使用限制在灵魂用户函数的范围内怎么办? lambda 的性质满足了这个要求,我将它用于这种情况。Well, one practical use I've found out is reducing boiler plate code. For example:
Without lambda, you may need to do something for different
bsize
cases. Of course you could create a function but what if you want to limit the usage within the scope of the soul user function? the nature of lambda fulfills this requirement and I use it for that case.C++ 11 引入了 lambda 表达式,允许我们编写可用于简短代码片段的内联函数。
通常 lambda 表达式中的返回类型由编译器本身计算,我们不需要显式指定 ->返回类型部分可以忽略,但在某些复杂的情况下,如条件语句中,编译器无法确定返回类型,我们需要指定它。
输出
通过访问封闭范围内的变量,lambda 表达式可以比普通函数拥有更多的功能。我们可以通过三种方式从封闭范围中捕获外部变量:
用于捕获变量的语法:
具有空捕获子句 [ ] 的 lambda 只能访问其本地变量。
输出:
C++ 11 introduced lambda expression to allow us write an inline function which can be used for short snippets of code
Generally return-type in lambda expression are evaluated by compiler itself and we don’t need to specify that explicitly and -> return-type part can be ignored but in some complex case as in conditional statement, compiler can’t make out the return type and we need to specify that.
Output
A lambda expression can have more power than an ordinary function by having access to variables from the enclosing scope. We can capture external variables from enclosing scope by three ways :
The syntax used for capturing variables :
A lambda with empty capture clause [ ] can access only those variable which are local to it.
Output:
对于初学者来说,之前(及时)给出的答案仍然不够清晰。特别是因为 lambda 可以定义/调用的形式不同。好吧,也许另一个初学者的回答(没有“知识的诅咒”)可能有助于澄清这些不同的形式。
输出:(
灵感来自 https://dotnettutorials.net/lesson/lambda-expressions -in-cpp/)
为了解决问题发布者的进一步问题,显示了一个演示,其中将数据与 lambda 一起用作数据处理器函数 à la map() 中的函数参数:
输出:
有关的更多信息这减少代码重复的典型用例可以从堆栈溢出 (2006) 的创始人之一那里找到:
https://www.joelonsoftware.com /2006/08/01/can-your-programming-language-do-this/。
顺便说一句:您可以将 lambda 表达式想象为在函数中定义了普通(数学)表达式,可以在另一个函数中使用(计算)这些表达式。 lambda 有效地实现了这一点,甚至更多。
Lambda 和其他技术还有助于在进行代码更改时减少 git diff 的“大小”。引用 Martin Cracauer 在他的介绍中编译时计算:
(我知道文章的标题不是关于 lambda 的,但是围绕文章的中心,可以找到一些通用的有用注释)
The answers given before (in time) are still missing some clarity for the beginner. Especially because of the different forms that a lambda can be defined/invoked. Well, perhaps an answer from another beginner (no 'curse of knowledge') may help clarify these different forms.
Output:
(inspiration got via https://dotnettutorials.net/lesson/lambda-expressions-in-cpp/)
To address the further questions of the question poster, a demonstration is shown where data is used together with lambda as function arguments in a data processor function à la map():
Output:
More information about this typical use case to reduce code repetitions can be found here from one of the founders of stack overflow (2006):
https://www.joelonsoftware.com/2006/08/01/can-your-programming-language-do-this/.
BTW: you could think of a lambda expression as if we had normal (mathematical) expressions defined in a function, where these can be used (computed) from within another function. The lambda effectively allows this and even more.
Lambdas and other techniques also help reduce git diff 'size' upon doing code changes. To quote Martin Cracauer in his introduction to Compile Time Computing:
(I know that the title of the article is not about lambdas, but around the center of the article, some general useful notes can be found)
它解决了一个问题: 使用输出参数函数来初始化 const 成员的构造函数中的调用的代码比 lambda 更简单
您可以通过调用通过返回其输出来设置其值的函数来初始化类的 const 成员作为一个输出参数。
One problem it solves: Code simpler than lambda for a call in constructor that uses an output parameter function for initializing a const member
You can initialize a const member of your class, with a call to a function that sets its value by giving back its output as an output parameter.
问题
C++ 包含有用的通用函数,例如 std::for_each 和 std::transform ,它们非常方便。不幸的是,它们使用起来也很麻烦,特别是如果您想要apply 对于特定函数来说是唯一的。
如果你只在那个特定的地方使用
f
一次,那么仅仅为了做一些琐碎的一次性事情而编写整个类似乎有点过分了。在 C++03 中,您可能会想编写如下内容,以将函子保持在本地:
但是这是不允许的,
f
不能传递给 C++03 中的模板 函数。新的解决方案
C++11 引入了 lambda,允许您编写内联匿名函子来替换 struct f。对于简单的小例子,这可以更清晰地阅读(它将所有内容都放在一个地方)并且可能更易于维护,例如以最简单的形式:
Lambda 函数只是匿名函子的语法糖。
返回类型
在简单情况下,会为您推导 lambda 的返回类型,例如:
但是,当您开始编写更复杂的 lambda 时,您很快就会遇到编译器无法推导返回类型的情况,例如:
要解决此问题,您需要允许使用
-> 显式指定 lambda 函数的返回类型T
:“捕获”变量
到目前为止,除了传递给 lambda 的变量之外,我们还没有使用任何其他变量,但我们也可以在 lambda 中使用其他变量。如果您想访问其他变量,您可以使用 capture 子句(表达式的
[]
),到目前为止,这些示例中尚未使用该子句,例如:您可以通过引用和值捕获,您可以分别使用
&
和=
指定:[&epsilon, zeta]
通过引用捕获 epsilon,通过值捕获 zeta[&]
捕获所有变量在 lambda 中按引用使用[=]
通过值捕获 lambda 中使用的所有变量[&, epsilon]
通过引用捕获 lambda 中使用的所有变量,但捕获 epsilon按值[=, &epsilon]
按值捕获 lambda 中使用的所有变量,但按引用捕获 epsilon生成的
operator()
是const
通过默认情况下,默认情况下访问它们时,捕获将是 const 。这会导致每次使用相同输入的调用都会产生相同的结果,但是您可以 将 lambda 标记为可变
,以请求生成的operator()
不可变常量。The problem
C++ includes useful generic functions like
std::for_each
andstd::transform
, which can be very handy. Unfortunately they can also be quite cumbersome to use, particularly if the functor you would like to apply is unique to the particular function.If you only use
f
once and in that specific place it seems overkill to be writing a whole class just to do something trivial and one off.In C++03 you might be tempted to write something like the following, to keep the functor local:
however this is not allowed,
f
cannot be passed to a template function in C++03.The new solution
C++11 introduces lambdas allow you to write an inline, anonymous functor to replace the
struct f
. For small simple examples this can be cleaner to read (it keeps everything in one place) and potentially simpler to maintain, for example in the simplest form:Lambda functions are just syntactic sugar for anonymous functors.
Return types
In simple cases the return type of the lambda is deduced for you, e.g.:
however when you start to write more complex lambdas you will quickly encounter cases where the return type cannot be deduced by the compiler, e.g.:
To resolve this you are allowed to explicitly specify a return type for a lambda function, using
-> T
:"Capturing" variables
So far we've not used anything other than what was passed to the lambda within it, but we can also use other variables, within the lambda. If you want to access other variables you can use the capture clause (the
[]
of the expression), which has so far been unused in these examples, e.g.:You can capture by both reference and value, which you can specify using
&
and=
respectively:[&epsilon, zeta]
captures epsilon by reference and zeta by value[&]
captures all variables used in the lambda by reference[=]
captures all variables used in the lambda by value[&, epsilon]
captures all variables used in the lambda by reference but captures epsilon by value[=, &epsilon]
captures all variables used in the lambda by value but captures epsilon by referenceThe generated
operator()
isconst
by default, with the implication that captures will beconst
when you access them by default. This has the effect that each call with the same input would produce the same result, however you can mark the lambda asmutable
to request that theoperator()
that is produced is notconst
.什么是 lambda 表达式?
C++ lambda 表达式的概念起源于 lambda 演算和函数式编程。
lambda 是一个未命名的函数,对于无法重用且不值得命名的简短代码片段非常有用(在实际编程中,而不是理论上)。
在 C++ 中,最小 lambda 表达式如下所示:
[]
是捕获列表,{}
是函数体。lambda-expression 的完整语法,包括属性、
noexcept
/throw
-规范、requires-clauses等比较复杂。捕获列表
捕获列表定义了 lambda 外部的哪些内容应在函数体内可用以及如何可用。
它可以是:
[x]
[&x]
[&]
[=]
this
并使成员函数在 lambda[this]
内可调用您可以混合任何上面的逗号分隔列表
[x, &y]
。Init-captures (C++14)
现在可以使用
=
初始化捕获列表的元素,称为 init-capture。这允许重命名变量并通过移动来捕获。取自标准的一个示例:
以及取自维基百科的一个示例,展示了如何使用
std::move
捕获:模板参数 (C++20)
自 C++20 以来,lambda 表达式可以具有 < a href="https://eel.is/c++draft/temp.pre#nt:template-parameter-list" rel="noreferrer">template-parameter-list:
这样的 通用 lambda 就像一个非模板
struct
带有调用运算符模板:参数列表
parameter-declaration-clause 与任何其他 C++ 函数中的相同。
当没有参数时可以完全省略,即
[](){}
等同于[]{}
。泛型 Lambda 函数 (C++14)
带有
auto
参数的 为 通用 lambda。如果此处
auto
相当于T
T
是周围范围内某处的类型模板参数):这就像 C++20 缩写函数模板:
返回类型(可能推导)
如果 lambda 只有一个 return 语句,则返回类型可以省略,并且具有隐式类型
decltype(return_statement)
。还可以使用尾随返回类型语法显式提供返回类型:
改进的返回类型推导 (C++14)
C++14 允许为每个函数推导返回类型,并且不将其限制为
return expression 形式的函数;
。这也扩展到了 lambda。默认情况下,lambda 的返回类型是按照其返回类型被声明为
auto
来推断的。可变 lambda (C++14)
如果 lambda 被标记为可变(例如
[]() mutable { }
),则允许更改已通过 value 捕获的值。mutable
表示 lambda 类型的调用运算符没有const
限定符。函数体
A block-statement 将在以下情况下执行: lambda 实际上被称为。
这成为呼叫操作员的主体。
用例
ISO 标准定义的库从 lambda 中受益匪浅,并提高了可用性几个标准,因为现在用户不必在某些可访问范围内使用小函子来弄乱他们的代码。
What is a lambda expression?
The C++ concept of a lambda expression originates in the lambda calculus and functional programming.
A lambda is an unnamed function that is useful (in actual programming, not theory) for short snippets of code that are impossible to reuse and are not worth naming.
In C++, the minimal lambda expression looks like:
[]
is the capture list and{}
the function body.The full syntax for a lambda-expression, including attributes,
noexcept
/throw
-specifications, requires-clauses, etc. is more complex.The capture list
The capture list defines what from the outside of the lambda should be available inside the function body and how.
It can be either:
[x]
[&x]
[&]
[=]
this
and making member functions callable within the lambda[this]
You can mix any of the above in a comma separated list
[x, &y]
.Init-captures (C++14)
An element of the capture list can now be initialized with
=
, which is called init-capture.This allows renaming of variables and to capture by moving. An example taken from the standard:
and one taken from Wikipedia showing how to capture with
std::move
:The template parameters (C++20)
Since C++20, lambda expressions can have a template-parameter-list:
Such a generic lambda is like a non-template
struct
with a call operator template:The parameter list
The parameter-declaration-clause is the same as in any other C++ function.
It can be omitted completely when there are no parameters, meaning that
[](){}
is equivalent to[]{}
.Generic Lambdas (C++14)
Lambdas with an
auto
parameter are generic lambdas.auto
would be equivalent toT
here ifT
were a type template argument somewhere in the surrounding scope):This works just like a C++20 abbreviated function template:
Return type (possibly deduced)
If a lambda has only one return statement, the return type can be omitted and has the implicit type of
decltype(return_statement)
.The return type can also be provided explicitly using trailing return type syntax:
Improved Return Type Deduction (C++14)
C++14 allows deduced return types for every function and does not restrict it to functions of the form
return expression;
. This is also extended to lambdas.By default, the return type of a lambda is deduced as if its return type was declared
auto
.Mutable lambda (C++14)
If a lambda is marked mutable (e.g.
[]() mutable { }
) it is allowed to mutate the values that have been captured by value.mutable
means that the call operator of the lambda's type does not have aconst
qualifier.The function body
A block-statement will be executed when the lambda is actually called.
This becomes the body of the call operator.
Use cases
The library defined by the ISO standard benefits heavily from lambdas and raises the usability several bars as now users don't have to clutter their code with small functors in some accessible scope.
Lambda 表达式通常用于封装算法,以便将它们传递给另一个函数。但是,可以在定义后立即执行 lambda:
在功能上等同于
这使得 lambda 表达式成为重构复杂函数的强大工具。首先将代码部分包装在 lambda 函数中,如上所示。然后可以逐步执行显式参数化过程,并在每个步骤之后进行中间测试。一旦代码块完全参数化(如删除
&
所示),您可以将代码移动到外部位置并使其成为正常函数。同样,您可以使用 lambda 表达式根据算法的结果初始化变量...
作为划分程序逻辑的一种方式,您甚至可能会发现它很有用将 lambda 表达式作为参数传递给另一个 lambda 表达式...
Lambda 表达式还允许您创建命名的 嵌套函数,可以是避免重复逻辑的便捷方法。当将一个不平凡的函数作为参数传递给另一个函数时,使用命名 lambda 看起来也更容易一些(与匿名内联 lambda 相比)。 注意:不要忘记右花括号后面的分号。
如果后续分析显示函数对象的初始化开销很大,您可能会选择将其重写为普通函数。
Lambda expressions are typically used to encapsulate algorithms so that they can be passed to another function. However, it is possible to execute a lambda immediately upon definition:
is functionally equivalent to
This makes lambda expressions a powerful tool for refactoring complex functions. You start by wrapping a code section in a lambda function as shown above. The process of explicit parameterization can then be performed gradually with intermediate testing after each step. Once you have the code-block fully parameterized (as demonstrated by the removal of the
&
), you can move the code to an external location and make it a normal function.Similarly, you can use lambda expressions to initialize variables based on the result of an algorithm...
As a way of partitioning your program logic, you might even find it useful to pass a lambda expression as an argument to another lambda expression...
Lambda expressions also let you create named nested functions, which can be a convenient way of avoiding duplicate logic. Using named lambdas also tends to be a little easier on the eyes (compared to anonymous inline lambdas) when passing a non-trivial function as a parameter to another function. Note: don't forget the semicolon after the closing curly brace.
If subsequent profiling reveals significant initialization overhead for the function object, you might choose to rewrite this as a normal function.