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