At pages 227-228 of Item 32 from Effective Modern C++, Scott Meyers presents the following chunck of code as a way to workaround the lack of generalized lambda captures in C++11.
// data is in scope
auto func =
std::bind(
[](const std::vector<double>& x) // I've renamed it x so there's no ambiguity in my description below
{ /* usses of x */ },
std::move(data)
);
Then he makes the following comment, which I don't quite understand overall.
By default, the
operator()
member function inside the closure class generated from a lambda isconst
. That has the effect of rendering all data members in the closureconst
within the body of the lambda. The move-constructed copy ofdata
inside the bind object is notconst
, however, so to prevent that copy ofdata
from being modified inside the lambda, the lambda's parameter is declared reference-to-const
. If the lambda were declaredmutable
,operator()
in its closure class would not be declaredconst
, and it would be appropriate to omitconst
in the lambda's parameter declaration:// data is in scope auto func = std::bind( [](std::vector<doubld>& x) mutable // ditto { /* uses of x */ }, std::move(data) );
I tried to break it down:
- (non-
mutable
) lambda closures have theoperator()
member functionconst
, - therefore they cannot modify captured variables;
(That lambda, however, is not capturing anything in the first place, so the following points seem unrelated to me...)
std::bind
copies (well, moves)data
in a non-const
member variable of thefunc
object;- since the lambda takes the parameter by reference (not by value, as the whole point was to emulate C++14's move-lambda captures), the programmer could modify
data
throughx
inside the body of the lambda (which could be nounintentional); - to avoid this, the parameter is made
const&
.
So, I don't get the point of the last period If the lambda were declared [...].