我打算用C ++编写一个记忆模式,最后采用以下方法
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;
}
奇怪的是,我的编译器VS 2012拒绝编译时出现以下错误
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)
在我看来,编译器故意将值作为const对象捕获所有内容。我找不到任何有关此行为的文档参考。
任何人都可以帮助我理解这里可能发生的事情吗?
答案 0 :(得分:14)
Lambdas的行为或多或少与函数对象相似;像函数对象一样,它们有一个函数调用操作符,即operator()
。对于非mutable
lambdas,此函数为const
:
[expr.prim.lambda]
5非泛型lambda表达式的闭包类型具有public 内联函数调用操作符[...] 此函数调用操作符或 当且仅当时,运算符模板被声明为
const
(9.3.1) lambda-expression的parameter-declaration-clause 后面没有mutable
强>
因为复制捕获的实体表现得好像它们是lambda的成员变量:
15 [...]对于由副本捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员。
和非mutable
成员无法在const
成员函数内修改([class.this] / 1,[dcl.type.cv] / 4) ,如果要修改捕获的实体,则必须声明mutable
lambda。
现在你的lambda看起来像这样:
class Helper
{
public:
int operator()(int) const;
private:
std::map<int, int> memo;
std::function<int(int)> fn;
};
您可以将mutable
lambda视为具有非const
operator()
,在您的情况下,lambda可以定义如下:
std::function<int(int)> helper = [=](int pos) mutable
// etc
答案 1 :(得分:6)
为了使lambda函数非const,你需要添加mutable
关键字:
std::function<int(int)> Memoize(std::function<int(int)> fn)
{
std::map<int, int> memo;
std::function<int(int)> helper = [=](int pos) mutable // <== HERE!!
{
if (memo.count(0) == 0)
{
memo[pos] = fn(pos);
}
return memo[pos];
};
return helper;
}