题
是否可以通过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;
}
更新: 由于这是一个古老的问题,因此如果C ++ 14中的设施可以帮助您,则可能会更新它。 C ++ 14中的扩展是否允许我们通过const引用捕获非const对象? ((2015年8月)
解决方案
const
截至N3092,不在语法上:
capture:
identifier
& identifier
this
文本仅提及逐行和逐个捕获,并且没有提及任何形式的const。
对我来说感觉就像是一种疏忽,但我没有非常紧密地遵循标准化过程。
其他提示
我认为捕获部分不应指定 const
, ,作为捕获手段,它只需要一种访问外部范围变量的方法。
在外部范围中更好地指定了指定符。
const string better_string = "XXX";
[&better_string](string s) {
better_string = s; // error: read-only area.
}
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;
}
但这与假设您的lambda必须与当前功能隔离,使其成为非lambda。
我认为您有三个不同的选择:
- 不要使用const引用,而是使用副本捕获
- 忽略它是可修改的事实
- 使用std ::绑定以绑定具有const引用的二进制函数的一个参数。
使用副本
关于Lambdas和Copy Capture的有趣部分是,这些部分实际上仅读取,因此完全按照您想要的操作。
int main() {
int a = 5;
[a](){ a = 7; }(); // Compiler error!
}
使用std :: bind
std::bind
降低函数的敏锐度。但是请注意,这可能/将通过功能指针导致间接函数调用。
int main() {
int a = 5;
std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}
有一个较短的方法。
请注意,在“ BEST_STRING”之前没有AMPERS。
它将是“ const std :: reference_wrapper << t >>” type。
[best_string = cref(best_string)](const string& s)
{
best_string = s; // fails
};
使用clang或等到修复此GCC错误:BUG 70385:通过参考const引用失败捕获lambda [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385]
使用const将简单地具有算法and和将字符串设置为原始值,换句话说,lambda不会真正将自己定义为函数的参数,尽管周围范围将具有额外的变量...不过,它不会将字符串定义为典型 &&best_string](字符串const s) 所以, ,如果我们只是将其留下来,试图捕获参考,那就更好了。