Lambda Capture by Value强制所有作用域对象为const

Abh*_*jit 8 c++ lambda visual-c++ c++11

我打算用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;
    }
Run Code Online (Sandbox Code Playgroud)

奇怪的是,我的编译器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)
Run Code Online (Sandbox Code Playgroud)

在我看来,编译器故意通过值捕获所有内容作为const对象.我找不到任何有关此行为的文档参考.

任何人都可以帮助我理解这里可能发生的事情吗?

use*_*267 14

Lambdas的行为或多或少与函数对象相似; 像函数对象一样,它们有一个函数调用操作符,即operator().对于非mutablelambdas,此函数是const:

[expr.prim.lambda]

5非泛型lambda表达式的闭包类型有一个公共内联函数调用操作符[...] 当且仅当lambda表达式的参数声明时,才声明此函数调用操作符或操作符模板const(9.3.1)条款没有跟着 mutable.

因为复制捕获的实体表现得好像它们是lambda的成员变量:

15 [...]对于由副本捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员.

并且不能在成员函数([class.this]/1,[dcl.type.cv]/4)中修改非mutable成员,如果要修改捕获的实体,则必须声明lambda.constmutable

你的lambda看起来像这样:

class Helper
{
public:
    int operator()(int) const;
private:
    std::map<int, int> memo;
    std::function<int(int)> fn;
};
Run Code Online (Sandbox Code Playgroud)

您可以将mutablelambda视为具有非lambda const operator(),在您的情况下,lambda可以定义如下:

std::function<int(int)> helper = [=](int pos) mutable
// etc
Run Code Online (Sandbox Code Playgroud)


Gal*_*lik 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;
    }
Run Code Online (Sandbox Code Playgroud)