C++ Lambda 捕获作为常量引用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3772867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Lambda capture as const reference?
提问by John Dibling
Is it possible to capture by const reference in a lambda expression?
是否可以通过 lambda 表达式中的常量引用进行捕获?
I want the assignment marked below to fail, for example:
我希望下面标记的作业失败,例如:
#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;
}
Update:As this is an old question, it might be good to update it if there are facilities in C++14 to help with this. Do the extensions in C++14 allow us to capture a non-const object by const reference? (August 2015)
更新:由于这是一个老问题,如果 C++14 中有工具可以帮助解决这个问题,最好更新它。C++14 中的扩展是否允许我们通过常量引用捕获非常量对象?(2015 年 8 月)
采纳答案by Steve M
const
isn't in the grammar for captures as of n3092:
const
不在 n3092 的捕获语法中:
capture:
identifier
& identifier
this
The text only mention capture-by-copy and capture-by-reference and doesn't mention any sort of const-ness.
文本仅提及按复制捕获和按引用捕获,并没有提及任何类型的常量。
Feels like an oversight to me, but I haven't followed the standardization process very closely.
对我来说感觉像是疏忽,但我并没有非常密切地遵循标准化过程。
回答by Piotr Skotnicki
回答by zhb
I think the capture part should not specify const
, as the capture means, it only need a way to access the outer scope variable.
我认为捕获部分不应该指定const
,因为捕获意味着它只需要一种访问外部作用域变量的方法。
The specifier is better specified in the outer scope.
说明符最好在外部范围内指定。
const string better_string = "XXX";
[&better_string](string s) {
better_string = s; // error: read-only area.
}
lambda functionis const(can't change value in its scope), so when you capture variable by value, the variable can not be changed, but the reference is not in the lambda scope.
lambda 函数是 const(不能在其作用域内改变值),所以当你按值捕获变量时,变量不能改变,但引用不在 lambda 作用域内。
回答by Klaim
I guess if you're not using the variable as a parameter of the functor, then you should use the access level of the current function. If you think you shouldn't, then separate your lambda from this function, it's not part of it.
我想如果您不使用变量作为函子的参数,那么您应该使用当前函数的访问级别。如果你认为你不应该,那么把你的 lambda 与这个函数分开,它不是它的一部分。
Anyway, you can easily achieve the same thing that you want by using another const reference instead :
无论如何,您可以通过使用另一个常量引用轻松实现您想要的相同内容:
#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;
}
But that's the same as assuming that your lambda have to be isolated from the current function, making it a non-lambda.
但这与假设您的 lambda 必须与当前函数隔离,使其成为非 lambda 相同。
回答by Alex
I think you have three different options:
我认为您有三种不同的选择:
- don't use const reference, but use a copy capture
- ignore the fact that it is modifiable
- use std::bind to bind one argument of a binary function which has a const reference.
- 不要使用常量引用,而是使用副本捕获
- 忽略它是可修改的事实
- 使用 std::bind 绑定具有 const 引用的二元函数的一个参数。
using a copy
使用副本
The interesting part about lambdas with copy captures is that those are actually read only and therefore do exactly what you want them to.
带有复制捕获的 lambda 的有趣之处在于它们实际上是只读的,因此完全按照您的要求执行。
int main() {
int a = 5;
[a](){ a = 7; }(); // Compiler error!
}
using std::bind
使用 std::bind
std::bind
reduces the arity of a function. Note however that this might/will lead to an indirect function call via a function pointer.
std::bind
减少函数的元数。但是请注意,这可能/将导致通过函数指针进行间接函数调用。
int main() {
int a = 5;
std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}
回答by Sergey Palitsin
There is a shorter way.
有一个更短的方法。
Note that there is no ampersand before "best_string".
请注意,“best_string”之前没有&符号。
It will be of a "const std::reference_wrapper<< T >>" type.
它将是“const std::reference_wrapper<< T >>”类型。
[best_string = cref(best_string)](const string& s)
{
best_string = s; // fails
};
回答by Saith
Using a const will simply have the algorithm ampersand set the string to it's original value, In other words, the lambda won't really define itself as parameter of the function, though the surrounding scope will have an extra variable... Without defining it though, it wouldn't define the string as the typical [&, &best_string](string const s)Therefore, its most likely better if we just leave it at that, trying to capture the reference.
Using a const will simply have the algorithm ampersand set the string to it's original value, In other words, the lambda won't really define itself as parameter of the function, though the surrounding scope will have an extra variable... Without defining it though, it wouldn't define the string as the typical [&, &best_string](string const s)Therefore, its most likely better if we just leave it at that, trying to capture the reference.
回答by user1448926
Use clang or wait until this gcc bug is fixed: bug 70385: Lambda capture by reference of const reference fails [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385]
Use clang or wait until this gcc bug is fixed: bug 70385: Lambda capture by reference of const reference fails [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385]