Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deducing Lambda Capture Types

Tags:

c++

c++11

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?

like image 575
Mr. Anderson Avatar asked Jun 28 '19 18:06

Mr. Anderson


1 Answers

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.

like image 75
Brian Bi Avatar answered Oct 30 '22 05:10

Brian Bi