Lambda按值捕获将所有作用域对象强制为const [英] Lambda Capture by Value forces all scoped object to const

查看:222
本文介绍了Lambda按值捕获将所有作用域对象强制为const的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算用C ++编写一个记忆模式,并最终采用以下方法

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;
    }

奇怪的是,我的编译器VS 2012拒绝编译,并出现以下错误

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)

在我看来,编译器有意按值将所有内容捕获为const对象.我找不到有关此行为的任何书面参考.

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?

推荐答案

Lambda的行为或多或少类似于函数对象.像函数对象一样,它们具有函数调用运算符,即operator().对于非mutable lambda,此函数为const:

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]

[expr.prim.lambda]

5非泛型lambda表达式的闭包类型有一个public 内联函数调用运算符[...] 此函数调用运算符或 当且仅当操作符模板被声明为const (9.3.1). lambda-expression的parameter-declaration-clause后面没有 mutable .

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 by mutable.

因为被副本捕获的实体的行为就好像它们是lambda的成员变量一样:

Because entities captured by copy behave as though they were member variables of the lambda:

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

15 [...] For each entity captured by copy, an unnamed non-static data member is declared in the closure type.

如果需要,可以在const成员函数([class.this]/1,[dcl.type.cv]/4)中修改

和非mutable成员 要修改捕获的实体,您必须声明mutable lambda.

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.

按其原样,您的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;
};

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

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

这篇关于Lambda按值捕获将所有作用域对象强制为const的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆