Copied const object in lambda closure not mutable
c++, c++11, lambda
Solution
First, the type of a lambda expression, which has capture, is a class type (5.1.2 Lambda expressions [expr.prim.lambda] #3)
That type has an `operator()` which is by default `const`, unless `mutable` is used in the lambda expression ([expr.prim.lambda] #5)
Next, for each entity captured as copy, a unnamed member is declared in the closure type. [expr.prim.lambda] #14]
If you explicitly build the (mostly) equivalent of the capture type, everything will naturally follow from the usual semantics for classes, const-qualified types and const qualified member functions.
Example:
struct S
{
void f();
void fc() const;
};
void g()
{
S s0;
// [s0] () { s0.f(); }; // error, operator() is const
[s0] () { s0.fc(); }; // OK, operator() is const, S::fc is const
[s0] () mutable { s0.f(); };
[s0] () mutable { s0.fc(); };
const S s1;
// [s1] () { s1.f(); }; // error, s1 is const, no matter if operator() is const
[s1] () { s1.fc(); };
// [s1] () mutable { s1.f(); }; // error, s1 is const, no matter if operator() is const
[s1] () mutable { s1.fc(); };
}
I guess the confusion stems from the fact that `mutable` in the lambda-declarator concerns the `const`-ness of the `operator()`, not the `mutable`-ility of the data members of the closure type. It would be more natural to use `const`, as with member functions, but I guess the standards committee wanted `const` to be the default.
Problem
I'm trying to capture a const object via copy in a (mutable) lambda. My compiler however complains, that the captured object is const. Should it not be possible to copy the object as non-const? ``` struct Foo { Foo(){} void Func(){} }; int main() { const Foo foo; [foo]() mutable { foo.Func(); }; } ``` Compiling with g++ 4.7.2: ``` testcase.cpp: In lambda function: testcase.cpp:10:29: error: no matching function for call to ‘Foo::Func() const’ testcase.cpp:10:29: note: candidate is: testcase.cpp:4:7: note: void Foo::Func() <near match> testcase.cpp:4:7: note: no known conversion for implicit ‘this’ parameter from ‘const Foo*’ to ‘Foo*’ ``` Compiling with clang++ 3.1: ``` testcase.cpp:10:20: error: member function 'Func' not viable: 'this' argument has type 'const Foo', but function is not marked const std::async([foo]() mutable { foo.Func(); }); ``` The Standard document (or rather the draft...) defines in 5.1.2.14 that "The type [...] is the type of the corresponding captured entity", so I guess that would include the cv-specifiers. It does not seem intuitive though.