I am new to templates and lambdas function and I am trying to understand what's happening in this piece of code:
function<void (const int &)> foo = [&](auto x) {
x = 42;
}
Here, I assume the compiler is able to tell from the auto
keyword that x
has type const int &
. Therefore, the compiler should not allow the assignment x = 42
.
However, this code compiles without error, which confuses me. Why does the compiler allow this? What did the compiler actually deduced for the auto
keyword?
CodePudding user response:
auto
is never deduced to a reference. It always deduces to a decayed type.
When passed a const int &
(or any reference to some type T
), then it will be deduced to int
(or the decayed type T
). (Or to be more precise, when passed an expression of type T
with any value category, it will always deduce to the decayed type T
. Types of expressions never include references, which are instead translated into value categories.)
You can still assign the lambda, because it is possible to initialize an int
from a const int&
(or more precisely from an lvalue expression of type const int
). This is what will happen when you call foo
.
So you are assigning here to a local parameter object inside the function. The assignment is not visible outside the lambda.
If you want to deduce a reference, use auto&&
. This however will then always deduce a reference. It also won't decay the type, so the const
will be retained.