I was intending to write a memorization pattern in C++ and ended up with the following approach
std::function<int(int)> Memoize(std::function<int(int)> fn)
{
std::map<int, int> memo;
std::function<int(int)> helper = [=](int pos)
{
if (memo.count(pos) == 0)
{
memo[pos] = fn(pos);
}
return memo[pos];
};
return helper;
}
Strangely, my compiler VS 2012, refused to compile with the following error
1>Source1.cpp(24): error C2678: binary '[' : no operator found which takes a left-hand operand of type 'const std::map<_Kty,_Ty>' (or there is no acceptable conversion)
It seems to me that the compiler deliberately captures everything by value as a const object. I cannot find any documented reference to this behavior.
Can any one help me understand what is possibly happening here?
Lambdas behave more or less like function objects; like a function object they have a function call operator, i.e. operator()
. For non-mutable
lambdas, this function is const
:
[expr.prim.lambda]
5 The closure type for a non-generic lambda-expression has a public inline function call operator [...] This function call operator or operator template is declared
const
(9.3.1) if and only if the lambda-expression’s parameter-declaration-clause is not followed bymutable
.
Because entities captured by copy behave as though they were member variables of the lambda:
15 [...] For each entity captured by copy, an unnamed non-static data member is declared in the closure type.
and non-mutable
members cannot be modified inside a const
member function ([class.this] / 1, [dcl.type.cv] / 4), if you want to modify the captured entities you will have to declare a mutable
lambda.
As it stands your lambda looks like this:
class Helper
{
public:
int operator()(int) const;
private:
std::map<int, int> memo;
std::function<int(int)> fn;
};
You can think of a mutable
lambda as having a non-const
operator()
, in your case the lambda can be defined as follows:
std::function<int(int)> helper = [=](int pos) mutable
// etc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With