Using an unchecked variable in lambda

I can not understand the example from the standard version of C ++ 14 N4140 5.1.2.12 [expr.prim.lambda] .

A lambda expression with an associated default capture that does not explicitly commit this or a variable with auto-storage duration (this excludes any identification expression that has been found to refer to an element associated with non-initcaptures data) say it is implicit captures an object (i.e., this or a variable) if the compound statement:

  • odr - uses an object or
  • denotes an object in a potentially-evaluated expression, where the encompassing full expression depends on the general parameter of the lambda declared within the scope of the lambda expression.

[Example:

 void f(int, const int (&)[2] = {}) { } // #1 void f(const int&, const int (&)[1]) { } // #2 void test() { const int x = 17; auto g = [](auto a) { f(x); // OK: calls #1, does not capture x }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; f(x, selector); // OK: is a dependent expression, so captures x }; } 

-end example]

All such implicitly captured objects must be declared within the scope of the lambda expression.

[Note. Implicit capture of an object with a nested lambda expression can cause it to be implicitly captured using the containing lambda expression (see below). Implicit use of odr of this can lead to implicit capture. -end note]

I thought that the beginning of the phrase a lambda-expression with an associated capture-default should forbid any implicit capture (and this is confirmed by the comment), so calling #1 will result in an error (something about using an un-captured variable). So how does it work? What will be the first argument of f ? What if g is called after leaving test() ? What if I change signature #1 to void(const int&) ?

-

upd: Thanks to everyone for explaining how this works. Later I will try to find and publish references to the standard about this case.

+4
source share
1 answer

As TC said in a comment, No. 1 does not require capture, since x is known at compile time and therefore baked into lambda. It doesn't seem like the f function is known at compile time, so it doesn't need to be captured.

I believe that if you change the signature of f to int const & , you are now trying to pass the address of a constant on the stack, thereby undergoing changes, and this will require capturing x by value or reference.

0
source

Source: https://habr.com/ru/post/1015447/


All Articles