Joh*_*ing 151 c++ lambda c++11 c++14
是否可以通过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";
for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
{
best_string = s; // this should fail
}
);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更新:由于这是一个老问题,如果C++ 14中有设施来帮助解决这个问题,那么更新它可能会更好.C++ 14中的扩展是否允许我们通过const引用捕获非const对象?(2015年8月)
Ste*_*e M 115
const 从n3092起,它不属于捕获的语法:
capture:
identifier
& identifier
this
Run Code Online (Sandbox Code Playgroud)
该文本仅提及逐个复制和按引用捕获,并未提及任何类型的常量.
感觉像对我的监督,但我没有非常密切地遵循标准化过程.
Pio*_*cki 91
C++ 14:
[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
best_string = s; // fails
};
Run Code Online (Sandbox Code Playgroud)
C++ 17:
[&best_string = std::as_const(best_string)](const string& s)
{
best_string = s; // fails
};
Run Code Online (Sandbox Code Playgroud)
zhb*_*zhb 12
我认为捕获部分不应该指定const,因为捕获意味着它只需要一种方法来访问外部范围变量.
在外部范围中更好地指定说明符.
const string better_string = "XXX";
[&better_string](string s) {
better_string = s; // error: read-only area.
}
Run Code Online (Sandbox Code Playgroud)
lambda函数是const(不能更改其范围内的值),因此当您按值捕获变量时,该变量不能更改,但该引用不在lambda范围内.
我想如果你没有使用变量作为仿函数的参数,那么你应该使用当前函数的访问级别.如果你认为你不应该,那么将你的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;
}
Run Code Online (Sandbox Code Playgroud)
但这与假设你的lambda必须与当前函数隔离,使其成为非lambda相同.
小智 6
有一个更短的方法。
请注意,“best_string”之前没有&符号。
它将是“const std::reference_wrapper<< T >>”类型。
[best_string = cref(best_string)](const string& s)
{
best_string = s; // fails
};
Run Code Online (Sandbox Code Playgroud)
http://coliru.stacked-crooked.com/a/0e54d6f9441e6867
我认为你有三种不同的选择:
有关复制捕获的lambda的有趣部分是那些实际上是只读的,因此完全按照你的意愿行事.
int main() {
int a = 5;
[a](){ a = 7; }(); // Compiler error!
}
Run Code Online (Sandbox Code Playgroud)
std::bind减少函数的优点.但请注意,这可能会导致通过函数指针进行间接函数调用.
int main() {
int a = 5;
std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}
Run Code Online (Sandbox Code Playgroud)