Why can't member variables be used unskilled in lambda if there are uncaught local variables?

A simple example:

class Foo { int x; void bar(int x) { [this]() -> void { x = 6; }(); } }; 

It does not compile in GCC, Clang, MVC or ICC ( see it live ). If I change void bar(int x) to void bar(int y) , or if I change x = 6; on this->x = 6; then it works great.

That doesn't make sense to me. The local variable x from the call to bar intentionally not written to lambda. The only x that makes sense is the Foo member variable.

Question: Is this the expected behavior, and if so, explain why?

+7
c ++ language-lawyer lambda shadowing
source share
2 answers

From cppreference :

To search for a name, determine the type and value of this pointer, and to access non-stationary members of the class, the operator of the call to the closure function is considered in the context of a lambda expression.

In the body of the method panel (int x), the token “x” refers to the method argument, not to a member of the class. The item is hidden. [NOTE: this is, of course, bad coding practice, but not illegal]

If you said x = 6 , where you have a lambda definition, you expect the local variable x (i.e. the by-value-value argument for the method) to be changed, not the x member, right?

So the only question is, can a local variable be implicitly captured by a lambda? I would say that compilers are pretty straightforward, explaining that this is not possible.

cppreference also clarifies this statement:

A variable can be used without capture if it does not (that is, it is not a local variable or it is static or stream local) or if it is not used in the lambda body.

Note: odr-used means that you need to know the address of the variable, not just its value. Assigning a value to a variable counts as an odr use.

Consider this code:

 class Foo { int george; void bar(int washington) { int martha = washington; washington = 7; int jefferson = washington; int adams = martha; george = 6; [this, jefferson]() -> void { this->george = 15; // legal because `this` is captured jefferson = adams; // legal because jefferson is explicitly // captured, and because adams is not // odr-used, so adams can be captured // implicitly. martha = 9; // not legal because it is an odr-use // of a local variable so martha is not // implicitly captured. }(); } 
+1
source share

An error has occurred:

error: the variable 'x' cannot be implicitly committed to lambda without a default value set

x = 6;

Note: 'x' is declared here void bar (int x) {^ Note: lambda expression starts here this → void {^ warning: private field 'x' is not used [-Wunused-private-field] int x;

This led me to the problem of defining (or more precisely, overriding) the variable x . You declare it both outside of bar() and as a parameter. The following code was compiled for me (using the tool you showed):

 class Foo { int x; void bar() { [this]() -> void { x = 6; }(); } }; 

Hope this helps.

0
source share

All Articles