以下代码
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
(作为一个整体)不是一个标识符吗?为什么编译器不能正确解析?
注意:本文中的所有标准参考均取自 C++ 标准草案 n3337。
该标准规定,capture 必须是
&
、=
、this
、identifier 或前面带有 &
的 identifier。
Lambda 表达式5.1.2
[expr.prim.lambda]
capture-list: capture ..._opt capture-list , capture ..._opt capture: identifier & identifier this
因为
parentItem.displayName
不是一个标识符,而是一个“类成员访问表达式”。编译器在拒绝您的代码片段时是正确的。
班级成员访问5.2.5p1
[expr.ref]
后缀表达式后跟点
或箭头.
,可选地后跟关键字->
(14.2),然后后跟 id 表达式,就是后缀表达式。计算点或箭头之前的后缀表达式;66 该计算的结果与 id 表达式一起确定整个后缀表达式的结果。template
自 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 的捕获列表中的 reference R 的名称将使 lambda 包含对 R 所指的引用,而这不是确实如此,如此片段所示。