Consider the following:
void test( const int &value )
{
auto testConstRefMutableCopy = [value] () mutable {
value = 2; // compile error: Cannot a
[C++11: 5.1.2/14]:
An entity is captured by copy if it is implicitly captured and the capture-default is=
or if it is explicitly captured with a capture that does not include an&
. 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 type of the corresponding captured entity if the entity is not a reference to an object, or the referenced type otherwise. [..]
The type of value
inside your lambda is const int
, because it was captured by copy from a const int&
.
Thus, even though the lambda's call operator function is not const
(you marked the lambda mutable
), the actual implicit member value
is of type const int
and cannot be mutated.
Frankly, this seems absurd; I would expect this rule to say that the referenced type loses const
ness, as it's a copy. The presence or absence of the mutable
keyword on the lambda itself (and, thus, the presence or absence of the const
keyword on the generated call operator function) should be the only access control here.
In C++14 you can work around this by capturing as [value=value]
, which uses the same rules as auto
and thus drops the const
. C++'s great, ain't it?