I am trying to create a class where in the constructor's body, a local member variable is initialized and reused in a lambda which is also initialized directly in the constructor's body. A very simple version of this looks like the following:
#include <iostream>
class TestClass {
public:
TestClass()
{
auto localMember = 0;
const auto incrementAndDisplay = [localMember] {
localMember++;
std::cout << "Member value is now increased to: " << localMember << std::endl;
};
incrementAndDisplay();
}
};
int main()
{
TestClass testClass;
return 0;
}
However, this code does not compile. GCC throws the following error message for the line where the local member is modified:
main.cpp:9:13: error: increment of read-only variable ‘localMember’
9 | localMember++;
| ^~~~~~~~~~~
I am confused by this error message, because I never labeled this variable to be const
and can modify it outside the lambda without any problems. However, if I declare localMember
as a class member, the code will compile without any problems.
My best guess at this point is that the lambda cannot seem to access the member "correctly" because it is only a temporary value and might be discarded later. However, I might be completely wrong about that.
The question is: Is there a way to use the variable in a lambda, without making it a class member? And if that is not possible, why not?
You are capturing the constructor's local variable by value.
Lambdas are implicitly immutable, and the captured localMember
is a member variable of your lambda (which you've even specified to be const
). In order to make it mutable, you need to remove const
and add mutable
:
/*const*/ auto incrementAndDisplay = [localMember]() mutable {
^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^
remove | add
|
copy of the variable defined in the surrounding function
If you actually wanted to increase the value of the variable localMember
that you defined outside of the lambda, you need to capture it by reference:
auto incrementAndDisplay = [&localMember] {
// ^
// capture by reference