作为const引用的Lambda捕获?

是否有可能通过在lambdaexpression式中的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"; 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月

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

 capture: identifier & identifier this 

该文本只提到了通过引用捕获和通过引用捕获,并没有提到任何types的常量。

感觉像是对我的疏忽,但我没有非常密切地遵循标准化过程。

更新:由于这是一个老问题,如果C ++ 14中有设施来帮助解决这个问题,可能会更新它。 C ++ 14中的扩展是否允许我们通过const引用捕获非const对象?

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

DEMO

我认为捕获部分不应该指定const ,因为捕获手段,它只需要一种方法来访问外部范围variables。

说明符在外部范围中更好地指定。

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

lambda函数是const(不能更改其范围中的值),所以当您通过值捕获variables时,该variables不能被更改,但引用不在lambda范围内。

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

无论如何,你可以通过使用另一个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; } 

但是,这与假设您的lambda必须与当前函数隔离,使其成为非lambdaexpression式一样。

我想你有三个不同的select:

  • 不要使用const引用,而要使用副本捕获
  • 忽略它是可修改的事实
  • 使用std :: bind绑定具有const引用的二进制函数的一个参数。

使用副本

关于带有复制捕获的lambdas的有趣部分是那些实际上是只读的,因此完全是你想要的。

 int main() { int a = 5; [a](){ a = 7; }(); // Compiler error! } 

使用std :: bind

std::bind减less了函数的参数。 但请注意,这可能会导致通过函数指针的间接函数调用。

 int main() { int a = 5; std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a); } 

有一个更短的路。

请注意,“best_string”之前没有“&”符号。

它将是一个“const std :: reference_wrapper << T >>”types。

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

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

使用铿锵声或等待,直到这个海湾合作委员会的错误是固定的:错误70385:通过引用的const引用捕获的Lambda失败[ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385 ]