Reputation: 29970
Look at this example (godbolt):
void foo(int &par) {
auto l = [par]() {
decltype(par) x;
};
}
This program does not compile, because the par
in decltype(par)
refers to the parameter in foo
, and not to the variable of the lambda (so decltype(par)
is actually a reference type, which needs to be initialized).
Here is a relevant quote from the standard of C++14 (sorry about quoting an old standard, but I think it's easier to understand).
expr.prim.lambda/18 (emphasis is mine):
"Every id-expression within the compound-statement of a lambda-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type. [ Note: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. Furthermore, such an id-expression does not cause the implicit capture of the entity. — end note ]"
And the standard makes sure that if decltype used on a non-id-expression, then even tough it doesn't odr-use the variable, the captured one is used (expr.prim.lambda/19):
"Every occurrence of decltype((x)) where x is a possibly parenthesized id-expression that names an entity of automatic storage duration is treated as if x were transformed into an access to a corresponding data member of the closure type that would have been declared if x were an odr-use of the denoted entity."
So, depending on these rules (and maybe the standard has other related rules), a variable in a lambda may refer to the captured one, or may refer to the original one in the enclosing function.
I have two questions:
(Note: a related previous question: What is the type of a by-value lambda capture of a reference?)
Upvotes: 11
Views: 243
Reputation: 11011
There are various ways to design with those dozen different explicit and implicit captures. Other ways may be similarly confusing or more wasteful. You are transforming a reference into copy with same name so it can happen to be confusing on its own.
Can do by-copy capture with an initialiser:
void foo(int &par) {
auto l = [cap = par]() {
decltype(cap) x; // no confusion about names
};
}
Upvotes: 1