Use init capture to move objects into closures in C++14; emulate init capture via hand-written classes or std::bind
in C++11.
In C++14
One nice improvement in C++14, compared with C++11, is that it supports int capture (a.k.a, generalized lambda capture), which makes it possible for us to specify:
- the name of a data memeber in the closure class generated from the lambda
- an expression initializing that data member
For example:
|
|
One thing to note in init capture: the left side of “=” is the name of the data member in the closure we’re specifying, which is in the closure class scope; the right side is the initializing expresion, which is the same scope as where the lambda is being defined. The code in the body of the lambda is in the scope of the closure class, so uses of pw
refer to the closure class data member.
In C++11
In C++11, it’s not possible to capture the result of an expression. We can still emulate the behaivor by either manually write a class:
|
|
or use std::bind
:
|
|
Some facts about std::bind
above:
std::bind
produces function objects (called bind object), which contains copies of all the arguments passed tostd::bind
following this rule: copy constructing the lvalue arguemnt, and move construct rvalue argument.- by default, the
operator()
member function inside the closure class generated from a lambda isconst
; as a contrast, the move-constructed copy ofWidget
inside bind object is notconst
, so we declare reference-to-const as the lambda’s parameter to prevent that copy ofWidget
from being modified inside the lambda1 - the lifetime of the bind is the same as that of the closure, so it’s possible to treat objects in the bind object as if they were in the closure.
-
We can declare lambda as
mutable
if we want to modify the copy inside the lambda:[](std::unique_ptr<Widget>& pw) mutable {...}
↩︎