Reputation: 28470
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:
mutable
) lambda closures have the operator()
member function const
,(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 the func
object;data
through x
inside the body of the lambda (which could be nounintentional);const&
.So, I don't get the point of the last period If the lambda were declared [...].
Upvotes: 0
Views: 50
Reputation: 28470
Ok, writing the question helped me understand I was simply losing sight of the initial motivation of that code: emulating a generalized lambda capture.
Maybe Scott Meyers also implies that it's natural that the writer of that code expects the bind object func
to behave like the desired lambda as it was coded with the same specifiers as the actual lambda stored inside func
(actually the text only refers to the mutable
specifier, maybe because it's the only one worth discussing).
In other words,
mutable
lambda stored inside func
through std::bind
, the programmer likely expects that func
will behave as the corresponding non-mutable
C++14 lambda, hence the const
of the parameter of the actual lambda stored in func
;mutable
, then the user expects func
to behave as the corresponding mutable
C++14 lambda, so he does not expect it to preserve the captured value unmodified, hence the lack of const
in the second chunk of code.Even shorter:
A non-mutable
lambda stored inside func
should not modify its argument(s), because the corresponding desired non-mutable
C++14 lambda would not modify its captured variable(s).
Upvotes: 1