empty lambda capture and static

W

Werner

Hi All,

I've got this little example compiling under GCC, but I'm
not sure it is compliant:

void foo()
{
static const double cCOEFFICIENT = 0.1;

auto x1 = []
{
return cCOEFFICIENT*10;
};
auto x2 = []
{
return cCOEFFICIENT*2;
};
}
The question is:

Where in the standard does it state that the static
constant defined at enclosing function scoped [is]
visible in the lambda when using an empty capture?

Kind regards,

Werner
 
V

Victor Bazarov

I've got this little example compiling under GCC, but I'm
not sure it is compliant:

void foo()
{
static const double cCOEFFICIENT = 0.1;

auto x1 = []
{
return cCOEFFICIENT*10;
};
auto x2 = []
{
return cCOEFFICIENT*2;
};
}
The question is:

Where in the standard does it state that the static
constant defined at enclosing function scoped [is]
visible in the lambda when using an empty capture?

The emptiness means that everything is captured by value. See
[expr.prim.lambda]/14. I think that's what you're asking.

V
 
J

Juha Nieminen

Victor Bazarov said:
The emptiness means that everything is captured by value. See
[expr.prim.lambda]/14. I think that's what you're asking.

What? I tought that "[=]" was used to capture everything by value.
 
V

Victor Bazarov

Victor Bazarov said:
The emptiness means that everything is captured by value. See
[expr.prim.lambda]/14. I think that's what you're asking.

What? I tought that "[=]" was used to capture everything by value.

Sorry, you're right. Misread the Standard. Unless captured by copy,
any implicitly captured entity is captured by reference.

V
 
W

Werner

The emptiness means that everything is captured by value. See

[expr.prim.lambda]/14. I think that's what you're asking.

I'm asking what "[]" captures.

At I understand [/14], it describes when a copy (or by value)
is captured.

From the text I understand that this is the case when a
"[=]" capture is specified ("capture default is ="), or
if an explicit capture exists not including &:

int a, b;
[a, &b] iow a is a copy, b is a reference.

.... but what would a, b be when an empty capture
is specified, and should it be visible in the scope
of the lambda?

[]
{
a ?
b ?
}

Kind regards,

Werner
 
V

Victor Bazarov

The emptiness means that everything is captured by value. See

[expr.prim.lambda]/14. I think that's what you're asking.

I'm asking what "[]" captures.

At I understand [/14], it describes when a copy (or by value)
is captured.

From the text I understand that this is the case when a
"[=]" capture is specified ("capture default is ="), or
if an explicit capture exists not including &:

int a, b;
[a, &b] iow a is a copy, b is a reference.

... but what would a, b be when an empty capture
is specified, and should it be visible in the scope
of the lambda?

[]
{
a ?
b ?
}

Yes, if no capture is specified, the paragraph 15 is the one you want, I
think. I misread the /14 to mean that implicit capture is always by
copy, sorry.

V
 
N

Noah Roberts

The emptiness means that everything is captured by value. See
[expr.prim.lambda]/14. I think that's what you're asking.
What? I tought that "[=]" was used to capture everything by value.

Sorry, you're right. Misread the Standard. Unless captured by copy,

any implicitly captured entity is captured by reference.

I believe you were actually correct the first time but not this one. The exception appears to be 'this', which must be captured explicitly or a default must be explicitly supplied. There are good reasons not to do so by using '[=]':

http://crazycpp.wordpress.com/2011/04/06/lambda-capture-and-object-lifetime/
 
V

Victor Bazarov

Victor Bazarov <[email protected]> wrote:
The emptiness means that everything is captured by value. See
[expr.prim.lambda]/14. I think that's what you're asking.
What? I tought that "[=]" was used to capture everything by value.

Sorry, you're right. Misread the Standard. Unless captured by copy,

any implicitly captured entity is captured by reference.

I believe you were actually correct the first time but not this one.
The exception appears to be 'this', which must be captured explicitly or
a default must be explicitly supplied. There are good reasons not to do
so by using '[=]':

Yes, that portion is kind of confusing. Here are the relevant quotes
from the Standard:

[expr.prim.lambda]/15:
<<An entity is captured by reference if it is implicitly or explicitly
captured but not captured by copy.>>

and

[expr.prim.lambda]/14:
<<An entity is captured by copy if it is implicitly captured and the
capture-default is = or if it is explicitly
captured with a capture that does not include an &.>>

What I understand from those two sentences is that if you need to
capture by copy, you have to either say '[=]' (which means everything is
captured by copy - capture default), or put the name of the captured
variable without the '&' in front of it, like '[a]'.

Now, my experimentation shows that unless any capture mode is specified,
nothing is actually captured. Is that what you're saying?

Should the following compile? And if so, what is the expected output?
Will 'a' be captured by reference in 'byref' closure?

#include <iostream>
int main()
{
int a = 42;
auto byref = []() { std::cout << "R:" << &a << a << '\n'; };
auto bycopy = [=]() { std::cout << "C:" << &a << a << '\n'; };
auto boo = [&a]() { a = 42; };
std::cout << " :" << &a << a << "\n";
byref(); bycopy(); boo(); byref(); bycopy();
}

Or should 'a' not be captured at all? Comeau online chokes on lambdas
altogether. VC++ 2010 refuses to compile the 'byref' initialization
(complaining about 'a' capture), unless I write [&], in which case
everything works what's expected.

So, again, are you saying that empty capture clause doesn't actually
capture anything?

I didn't find that article relevant to the original question, sorry.

V
 
V

Victor Bazarov

On 8/2/2012 9:22 AM, Juha Nieminen wrote:


The emptiness means that everything is captured by value. See

[expr.prim.lambda]/14. I think that's what you're asking.



What? I tought that "[=]" was used to capture everything by value.

Sorry, you're right. Misread the Standard. Unless captured by copy,

any implicitly captured entity is captured by reference.

I believe you were actually correct the first time but not this one.
The exception appears to be 'this', which must be captured explicitly or
a default must be explicitly supplied. There are good reasons not to do
so by using '[=]':

Yes, that portion is kind of confusing. Here are the relevant quotes
from the Standard:

[expr.prim.lambda]/15:
<<An entity is captured by reference if it is implicitly or explicitly
captured but not captured by copy.>>

and

[expr.prim.lambda]/14:
<<An entity is captured by copy if it is implicitly captured and the
capture-default is = or if it is explicitly
captured with a capture that does not include an &.>>

What I understand from those two sentences is that if you need to
capture by copy, you have to either say '[=]' (which means everything is
captured by copy - capture default), or put the name of the captured
variable without the '&' in front of it, like '[a]'.

Now, my experimentation shows that unless any capture mode is specified,
nothing is actually captured. Is that what you're saying?

Should the following compile? And if so, what is the expected output?
Will 'a' be captured by reference in 'byref' closure?

#include <iostream>
int main()
{
int a = 42;
auto byref = []() { std::cout << "R:" << &a << a << '\n'; };
auto bycopy = [=]() { std::cout << "C:" << &a << a << '\n'; };
auto boo = [&a]() { a = 42; };
std::cout << " :" << &a << a << "\n";
byref(); bycopy(); boo(); byref(); bycopy();
}

Or should 'a' not be captured at all? Comeau online chokes on lambdas
altogether. VC++ 2010 refuses to compile the 'byref' initialization
(complaining about 'a' capture), unless I write [&], in which case
everything works what's expected.

Oh, and if I change the declaration of 'a' to

static int a = 42;

then it becomes accessible in every closure without the need to capture,
and actually VC++ complains that it can't capture 'a' by ref in the
'boo' closure. The code that compiles is:

#include <iostream>
int main()
{
int a = 42;
auto byref = [&]() { std::cout << "R:" << &a << a << '\n'; };
auto bycopy = [=]() { std::cout << "C:" << &a << a << '\n'; };
auto boo = [&a]() { a = 42; };
std::cout << " :" << &a << a << "\n";
byref(); bycopy(); boo(); byref(); bycopy();
}

and the output from 'byref' and 'bycopy' is the same (compared to the
other sample where the addresses are different based on the capture).
So, again, are you saying that empty capture clause doesn't actually
capture anything?


I didn't find that article relevant to the original question, sorry.

V

V
 
C

Casey

So, again, are you saying that empty capture clause doesn't actually
capture anything?

The capture rules are spelled out in 5.1.2/10-12: an entity is explicitly captured if it appears in the capture list, implicitly captured if a capture-default is specified. An entity is captured if it is explicitly or implicitly captured.

Consequently, an empty lambda-introducer "[]" captures nothing.
 
V

Victor Bazarov

So, again, are you saying that empty capture clause doesn't actually
capture anything?

The capture rules are spelled out in 5.1.2/10-12: an entity is explicitly captured if it appears in the capture list, implicitly captured if a capture-default is specified. An entity is captured if it is explicitly or implicitly captured.

Consequently, an empty lambda-introducer "[]" captures nothing.

Which then leads to the conclusion that a static object is not really
"captured". It's accessible since it's in the scope and that's all it
is. Right?

V
 
C

Casey Carter

Which then leads to the conclusion that a static object is not really
"captured". It's accessible since it's in the scope and that's all it
is. Right?

Yes, capture only applies to *this* and "variables with automatic
storage duration declared in the reaching scope of the local lambda
expression" (5.1.2/10-11).
 
C

Casey Carter

Hi All,

I've got this little example compiling under GCC, but I'm
not sure it is compliant:

void foo()
{
static const double cCOEFFICIENT = 0.1;

auto x1 = []
{
return cCOEFFICIENT*10;
};
auto x2 = []
{
return cCOEFFICIENT*2;
};
}
The question is:

Where in the standard does it state that the static
constant defined at enclosing function scoped [is]
visible in the lambda when using an empty capture?

Kind regards,

Werner

The rules for lambda capture only apply to *this* and to variables with
automatic storage duration; names for other kinds of entities aren't
treated specially. That static is visible for the same reason it would
be if you wrote:

void foo()
{
static const double cCOEFFICIENT = 0.1;

{
return cCOEFFICIENT*10;
}
{
return cCOEFFICIENT*2;
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top