This question already has an answer here:
How can I accurately predict from a capture which type of member will be created in the lambda?
In C++, I thought that capturing an object of type T
by value creates a data member of type const T
, and by reference T&
. But when compiling this:
#include <iostream>
struct A{
A(){std::cout<<"A\n";}
A(const A&){std::cout<<"A&\n";}
void cf()const{}
void f(){}
};
int main(){
A a;
A& ra=a;
const A& cra=a;
auto f00 = [ra, cra, &a]()-> void{
//Fixed:
//ra is A, cra is const A, a is A&
//lambda is void operator()()const
a.cf(); a.f();//pass
//ra.cf(); ra.f();//ra.f compilation err.
//cra.cf(); cra.f();//cra.f compilation err
};
//f00(); //A&,A&
auto f01 = [ra, cra, &a]()mutable-> void{
//Fixed:
//ra is A, cra is const A, a is A&
//lambda is void operator()()mutalbe
a.cf(); a.f();//pass
ra.cf(); ra.f();//pass
cra.cf(); cra.f();//cra.cf pass, but cra.f error, why?
};
//f01(); //A&,A&
auto f02 = [&ra, &cra, &a]()mutable-> void{
//Fixed:
//ra is A&, cra is const A&, a is A&
//lambda is void operator()()mutable
a.cf(); a.f();//pass
ra.cf(); ra.f();//pass
//cra.cf(); cra.f();//cra.cf pass, but cra.f error, why?
};
f02(); //
return 0;
}
I encountered the following compilation error:
test_lambda.cpp:26:25: error: passing 'const A' as 'this' argument discards qualifiers [-fpermissive]
cra.cf(); cra.f();//pass, cra.f error
^
test_lambda.cpp:8:10: note: in call to 'void A::f()'
void f(){}
^
Does this mean that cra
has really been captured by reference, rather than by a copy of the referred object as I expected?
The type of the captured entities remains the same, except that references to objects are captured as copies of the referenced objects. From CPP Reference on Lambda Closure Types:
In all of your lambdas, the type of the closure member
cra
isA
. They are not, themselves,const
. However, the default function-calloperator()
of the lambda is. The error on line 17 aboutf00
is caused by the fact that you attempt to modify an closure member created by copy when callingra.f()
, but due to it having anoperator() const
, it can only performconst
operations on its members.This is why in all three functions calling the non-
const A::f
oncra
gives a compilation error. You should addmutable
after the lambda argument list to allow performing non-const
operations on by-copy closure members.