以下代码
void CMainWindow::someMethod(const CLocationsCollection& parentItem)
{
auto f = [this, parentItem.displayName](){};
}
给了我一个错误:
错误C2143:语法错误:在'。'之前缺少']'。
如果我想通过ref捕获parentItem.displayName
,我会为它创建一个非依赖别名标识符:
const QString& name = parentItem.displayName;
auto f = [this, &name](){}; // Or should it be [this, name] ?
但是我需要按值捕获它,我不想捕获整个parentItem
,因为它很重。任何解决方案?
P上。 S.捕获列表中的名称必须是标识符。 parentItem.displayName
(作为一个整体)不是标识符吗?为什么编译器无法正确解析它?
答案 0 :(得分:12)
注意:本文中的所有标准参考均来自C ++标准草案n3337。
标准规定捕获必须为&
,=
,this
,标识符或标识符以&
开头。
5.1.2
Lambda表达式[expr.prim.lambda]
capture-list: capture ..._opt capture-list , capture ..._opt capture: identifier & identifier this
由于parentItem.displayName
不是标识符,而是"类成员访问表达式" 。拒绝你的代码片段时编译器是正确的。
5.2.5p1
类成员访问权限[expr.ref]
后缀表达式后跟点
.
或箭头->
,可选地后跟关键字template
(14.2),然后是id-expression,是后缀表达。评估点或箭头之前的后缀表达式; 66 该评估的结果与id-expression一起确定整个后缀表达式的结果。
在 C ++ 14 中,将能够使用 init-capture 来规避手头的问题,将其视为代码段下面。它将创建一个名为 display_name 的捕获,使用 parentItem.displayName 的值进行初始化。
[display_name = parentItem.displayName](){ ... };
遗憾的是, C ++ 11 中没有这样的功能。因此,问题的解决方案是对数据成员进行本地引用,然后在创建lambda时捕获该引用。
auto& lmb_display_name = parentItem.displayName;
[lmb_display_name](){ ... }; // the lambda will have a copy of `parentItem.displayName`
注意:您的原始帖子似乎暗示了lambda的捕获列表中引用 R 的名称使lambda包含对 R 引用的引用的引用,这是this snippet可以看到的不是真的。