I've recently found that capturing a const
object by value in a lambda, implies that the variable inside the labmda's body (i.e. the lambda's data member) is also const
.
For example:
const int x = 0;
auto foo = [x]{
// x is const int
};
This behavior is mentioned in § 8.1.5.2 in the draft for C++17:
For each entity captured by copy, an unnamed non-static data member is declared in the closure type. The declaration order of these members is unspecified. The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise. A member of an anonymous union shall not be captured by copy.
I would expect that deducing type of captured variables will be the same as deducing auto.
Is there a good reason for having different type-deduction rules for captured types?
In your example, it would not be possible to modify x
since the lambda is not mutable
, which makes the function call operator const
. But even if the lambda is mutable
, it's true that the quoted passage makes the type of x
in the lambda const int
.
If I remember correctly, this was a deliberate design decision in C++11 to make the use of x
within the lambda behave similarly to the use of x
in the enclosing scope. That is,
void foo(int&);
void foo(const int&);
const int x = 0;
foo(x); // calls foo(const int&)
auto foo = [x]() mutable {
foo(x); // also calls foo(const int&)
};
This helps to avoid bugs when, e.g., some code is rewritten from having an explicit loop to calling a standard library algorithm with a lambda.
If I'm wrong about this recollection, hopefully someone with the right answer will step in and write their own answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With