是否有可能在lambda表达式中通过const引用捕获?

我希望下面标记的作业失败,例如:

#include <algorithm>
#include <string>

using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";

    for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
      {
        best_string = s; // this should fail
      }
    );
return 0;
}

更新:由于这是一个老问题,如果c++ 14中有帮助解决这个问题的工具,更新它可能会很好。c++ 14中的扩展允许我们通过const引用捕获非const对象吗?(2015年8月)


当前回答

在c++14中使用static_cast / const_cast:

[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
    best_string = s; // fails
};

DEMO


在c++17中使用std::as_const:

[&best_string = std::as_const(best_string)](const string& s)
{
    best_string = s; // fails
};

演示2

其他回答

从n3092开始,Const不在捕获语法中:

capture:
  identifier
  & identifier
  this

文本只提到了复制捕获和引用捕获,没有提到任何形式的const-ness。

对我来说,这是一个疏忽,但我没有非常密切地遵循标准化过程。

有一条较近的路。

注意在"best_string"之前没有&号。

它将是一个const std::reference_wrapper<T>类型。

[best_string = std::cref(best_string)](const string& s)
{
    best_string = s; // fails
};

http://coliru.stacked-crooked.com/a/0e54d6f9441e6867

使用clang或等待,直到这个gcc错误被修复: bug 70385:通过const引用捕获Lambda失败[https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385]

我想如果你不使用变量作为函子的参数,那么你应该使用当前函数的访问级别。如果你认为不应该,那么把和这个函数分开,它不是函数的一部分。

不管怎样,你可以通过使用另一个const引用来轻松实现你想要的东西:

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";
    const string& string_processed = best_string;

    for_each( &strings[0], &strings[num_strings], [&string_processed]  (const string& s)  -> void 
    {
        string_processed = s;    // this should fail
    }
    );
    return 0;
}

但这和假设你的必须与当前函数隔离是一样的,使它成为非。

我认为捕获部分不应该指定const,因为捕获意味着,它只需要一种访问外部作用域变量的方法。

说明符最好在外部作用域中指定。

const string better_string = "XXX";
[&better_string](string s) {
    better_string = s;    // error: read-only area.
}

Lambda函数是const(不能在其作用域中更改值),因此当您按值捕获变量时,变量不能更改,但引用不在Lambda作用域中。