There are situations when it is necessary to capture a unique_ptr in a lambda expression. For instance, when a unique_ptr is pointing to a large amount of data that is very expensive to copy and has to be processed by a lambda. Another case in point is, a lambda executing in a separate thread for asynchronous processing needs to capture a unique_ptr. We will consider one of those cases here.
Prior to C++14, it was not possible to capture a unique_ptr in a lambda. The C++14 standard introduced Generalized lambda capture, which makes it possible to capture a unique_ptr in a lambda expression. The Generalized lambda capture is not specific to unique_ptr, it is a general solution. In brief, since C++14 it is possible to define and initialize a new variable in the capture clause of a lambda, e.g.:
std::string str("Hello World");
auto lc = [s = str]() {
//...
};
//It is also possible to move-construct a variable
auto lm = [s = std::move(str)]() {
//...
};
This article assumes we are working with C++14 here.
Assume a struct, Data, can hold a large amount of data:
struct Data {
// Holds large data
};
The CreateDataProcessor dynamically allocates Data and fills it with a large amount of data, which is very expensive to copy. A lambda expression that can be called to process the data is returned. The returned lambda needs a capture clause (which replaces /*Capture pData*/
below) that can capture the unique_ptr pData
appropriately:
auto CreateDataProcessor() {
// Dynamically allocate Data
auto pData = std::make_unique<Data>();
// Fill Data here
// Return a lambda that processes data
return [/*Capture pData*/]( ) {
// Process Data in pData
};
}
Select the correct capture clause for above lambda that compiles and runs without any error (check Explanations for details):