Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non local lambda and capturing variables - what does "block scope" means

Tags:

c++

c++11

lambda

I'm currently playing with c++11 lambdas and found a example that I can't understand. According to the Standard:

A lambda-expression whose smallest enclosing scope is a block scope (3.3.3) is a local lambda expression; any other lambda-expression shall not have a capture-list in its lambda-introducer

so, I created trivial example:

int a = 10;
auto x  = [a] { return 1;};
int main() {
    int k = 5;
    auto p = [k]{ return k; };
    return 0;
}

The code in ideone: http://ideone.com/t9emu5

I was expecting that this code will not compile because of capturing variable in non-block scope (or at least think that the auto x = ... part is not in the block-scope). But the code is compiling - is it ok?

If is it ok - what the block scope is?

(I'm not sure what compiler version I use because currently I have access only to ideone site.

Thanks for explaining!

like image 337
matekm Avatar asked Oct 13 '13 12:10

matekm


1 Answers

It looks like this is a compiler extension. g++4.8.1 compiles this while giving a warning:

warning: capture of variable ‘a’ with non-automatic storage duration [enabled by default]

clang++3.4 doesn't compile this:

error: 'a' cannot be captured because it does not have automatic storage duration

Both refer to [expr.prim.lambda]/10

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

It seems they don't additionally check the enclosing scope of the lambda, I can imagine it would be redundant (there are no names of variables with automatic storage duration at non-block/namespace scope).


A block scope is defined in [basic.scope.block]/1

A name declared in a block (6.3) is local to that block; it has block scope.

And a block is defined as:

So that several statements can be used where one is expected, the compound statement (also, and equivalently, called “block”) is provided.

     compound-statement:
         { statement-seqopt }

So you're right that your globally declared lambda is not in a block scope.

like image 89
dyp Avatar answered Oct 20 '22 15:10

dyp