C++ has supported lambda functions since C++11, and post-C++14 even supported generic lambdas. C++17 adds a quirky feature to enable ‘copy capture’ of ‘this’. Here’s an example of it in action:
struct MyStruct { auto lambda_with_this() // Before C++17, copies this pointer { auto f = [this]{ return value; }; return f; } auto lambda_with_star_this() // C++17 - takes a local copy of *this { auto f = [*this]{ return value; }; return f; } int value; }; TEST( Cpp17, lambda_capture_this ) { MyStruct s{ 42 }; auto f = s.lambda_with_this(); s.value = 101; EXPECT_EQ( 101, f() ); } TEST( Cpp17, lambda_capture_star_this ) { MyStruct s{ 42 }; auto f = s.lambda_with_star_this(); s.value = 101; EXPECT_EQ( 42, f() ); }
Notice that in the second case, we capture a copy of our object – so the lambda returns the value held at the point of capture (42) rather than the value when it is called (101). This can be very important if ‘this’ has been destroyed between the creation of the lambda and the time at which it’s called.
Now, C++14 also supported generalised lambda capture, which meant you could (re-)name variables when capturing (and provided a neat way to capture-by-move):
auto f = [tmp = *this]{ return tmp.value; };
But the C++17 code is more concise. See this useful StackOverflow post for more discussion.
Another advance in C++17 is that lambdas are implicitly constexpr – so you can now use them in compile-time contexts, like declaration of std::array:
// lambda explicitly constexpr since C++17 auto square = []( auto v ){ return v*v; }; TEST( Cpp17, lambda_implicitly_constexpr ) { // std::array calls 'square()' at compile time std::array<int, square(4)> values; EXPECT_EQ( 16, values.size() ); }
See also the previous C++17 post.