访问 C++14 lambda 捕获,如结构成员
Posted
技术标签:
【中文标题】访问 C++14 lambda 捕获,如结构成员【英文标题】:Access C++14 lambda captures like struct members 【发布时间】:2014-02-18 20:48:29 【问题描述】:AFAIK,C++11/14 不允许在定义 lambda 时就地定义新的返回类型。但是,似乎 C++14 lambda 捕获表达式本质上创建了一个具有一个或多个“成员”和一个运算符 () 的匿名类型。那么,为什么编译器不允许从外部 lambda 访问捕获的成员。我虚弱的头脑无法处理 C++ 的复杂性,但它对您来说听起来像是一种合理的语言扩展吗?这是一个例子。
vector<string> words = "Stack", "Overflow" ;
auto l = [w = words](); // almost like a C# anonymous type
cout << l.w[0]; // does not work.
【问题讨论】:
“AFAIK,C++11/14 不允许在定义 lambda 时就地定义新类型。” 你是什么意思?在 lambda-capture 内部还是 lambda-body 内部? 我的意思是更像一个新的返回类型。 AFAIK,C++中有匿名本地类vector<string> words = "Stack", "Overflow" ; struct decltype(words) w; lwords; cout << l.w[0];
Live example
当然不行。数据成员应该是私有的!
@n.m.如果类型暴露在“模块”之外,这是合理的。在本地上下文中(例如,在表达式、函数甚至类中),我更喜欢使用公共成员。
【参考方案1】:
现状
当 lambda init-captures 被添加到语言中时讨论过这个问题。该标准的当前工作草案 (N3797) 说(在 [expr.prim.lambda]p11 中):
对于每一个 init-capture,一个由 init-capture 的 identifier 命名的非静态数据成员在闭包类型中声明.
标准没有指定该成员的访问权限,因此不清楚这是否有效:
auto x = [n(0)] ;
int k = x.n; // ok?
init-captures 的这个和其他一些规范问题导致了国家机构对标准草案的 GB3 评论,该标准草案由 C++ 核心工作组处理为core issue 1760。在讨论该问题时,核心工作组决定 lambda 的 init-captures 不应成为闭包对象的可访问成员。
第 1760 号问题的决议(已获 CWG 批准,但尚未获得整个委员会的批准)将规范更改为:
init-capture 的行为就好像它声明并显式捕获了
“auto init-capture ;”
形式的变量,其声明区域是 lambda-expression 的 复合语句 [...]
这个新措辞清楚地表明 init-capture 不会添加闭包对象的可命名成员,而是像任何其他 lambda 捕获一样工作。
作为语言扩展
使 init-captures 成为闭包类型的可访问成员当然是可能的(在我实施决议之前,我在 clang 中的 init-captures 的初始实现就是这样做的第 1760 期)。这似乎也是一个有用的功能,但它也允许在 init-captures 不可见的常见情况下违反 lambda-expressions 的封装。
【讨论】:
【参考方案2】:如果我理解这一点,您希望能够访问在 lambda 中捕获的变量。但是根据Get captured variables from lambda?上的最高答案,这是不可能的。
这是不可能的设计
5.1.2 [expr.prim.lambda]
15 [...] 对于复制捕获的每个实体,在闭包类型中声明了一个未命名的非静态数据成员。这些成员的声明顺序未指定。 [...]
16 [...] 未指定是否有其他未命名的非静态数据成员 在通过引用捕获的实体的闭包类型中声明。
捕获的变量未命名(或至少具有未命名的名称) 凡人无法言说的),他们的申报顺序是故意的 未指定。闭包中的引用捕获甚至可能不存在 输入。
我的大胆强调。
【讨论】:
叹息!我希望它是一个可访问的命名非静态成员,以防复制捕获。 正如我在引用的答案中所说,您并不是真的想要那样,您只是认为自己想要。支持你想要的会限制实现并阻止优化。如果您想访问命名成员,那么不要使用 lambda 表达式!以上是关于访问 C++14 lambda 捕获,如结构成员的主要内容,如果未能解决你的问题,请参考以下文章
在 c++14 lambda 表达式中捕获和移动 unique_ptr
如何从 C++14 中的广义 lambda 捕获返回包含 std::unique_ptr 的 std::function?