Lambda Expression

Lambda Expression

Lambda Expression

Init Capture

This feature is introduced since C++14, it also called generalized lambda capture.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
namespace {
class Widget {
private:
std::string name_;

public:
explicit Widget(std::string name) : name_(std::move(name)) {}

friend std::ostream &operator<<(std::ostream &os, const Widget &item) {
os << item.name_;
return os;
}

void test_capture_member() {
[name = std::ref(name_)] { std::cout << "name: " << name; }();
}
};

} // namespace

void test_init_capture() {
auto pw_outer = std::make_unique<Widget>("widget");

// test init capture.
[pw = std::move(pw_outer)] { std::cout << *pw.get(); }();
[pw = std::make_unique<Widget>("widget2")] { std::cout << *pw.get(); }();

auto pw = std::make_unique<Widget>("test");
// test class member capture.
pw->test_capture_member();
}

Captures apply only to non-static local variables (including parameters) visible in the scope where
the lambda is created. So if you want to capture a class member, the original way is using a local
variable. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace {

class Widget {
private:
std::string name_;

public:
explicit Widget(std::string name) : name_(std::move(name)) {}

void test_capture() {
auto &name = name_;
[name] { std::cout << name; }();
}
};

} // namespace

Since C++14, we can use init capture feature for this situation. It means we can define a new
variable and initialize this local variable using class member during lambda capture. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace {
class Widget {
private:
std::string name_;

// ...

void test_capture() {
[name = std::ref(name_)] { std::cout << name; }();
}
};

} // namespace

Please visit site for complete code Lambda Expression Testcase

References

  • Item 31: Avoid default capture modes, Effective Modern C++, Scott Meyer
Author

Yuanjun Ren

Posted on

2022-11-08

Updated on

2022-11-13

Licensed under

Comments