像struct成员一样访问C ++ 14 lambda捕获 [英] Access C++14 lambda captures like struct members

查看:110
本文介绍了像struct成员一样访问C ++ 14 lambda捕获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

AFAIK,C ++ 11/14不允许在定义lambda时就地定义新的返回类型。但是,似乎C ++ 14 lambda捕获表达式实质上创建了一个带有一个或多个成员和一个运算符()的匿名类型。因此,为什么编译器不允许从Lambda 外部访问捕获的成员。我虚弱的头脑无法处理C ++的复杂性,但这听起来对您来说是合理的语言扩展吗?这是一个示例。

  vector< string>单词= {堆栈,溢出}; 
auto l = [w = words](){}; //几乎就像C#匿名类型
cout<< l.w [0]; //不起作用。


解决方案

现状



在将lambda init-captures 添加到语言时,对此进行了讨论。该标准(N3797)的当前工作草案(在 [expr.prim.lambda] p11 中)说:


对于每个 init-capture ,在闭包类型中声明一个由 init-capture identifier 命名的非静态数据成员。


该标准没有指定该成员的访问权限,因此不清楚这是否有效: / p>

  auto x = [n(0)] {}; 
int k = x.n; // 好?

此问题和 init-captures 的其他一些规范问题导致了国家机构在标准草案中对GB3进行评论,该标准草案由C ++核心工作组作为 core处理发行1760 。在讨论该问题时,核心工作组决定,lambda的 init-captures 应该不是是闭合对象的可访问成员。



第1760号决议(已由CWG批准,但尚未由全体委员会批准)将规范更改为改为:


init-capture 的行为就像声明并明确捕获了格式为 auto init-capture; 的变量一样区域是 lambda表达式复合语句 [...]


此新措辞清楚地表明, init-capture 不会添加闭包对象的可命名成员,而是像其他任何lambda捕获一样起作用。



作为语言扩展



使 init-captures 成为闭包的可访问成员类型当然是可能的(我最初对 ini的实现在我实施问题1760的解决方案之前,用clang的t-captures 做到了这一点。它似乎也是有用的功能,但在 init-captures 不可见的常见情况下,它也允许违反 lambda-expressions 的封装。 / p>

AFAIK, C++11/14 does not allow in-place definition of a new return type while defining a lambda. However, it seems a C++14 lambda capture expression essentially creates an anonymous type with one or more "members" and an operator (). So, why is that the compiler does not allow access to the captured members from outside the lambda. My feeble mind cannot handle the complexities of C++ but does it sound like a reasonable language extension to you? Here is an example.

vector<string> words = { "Stack", "Overflow" };
auto l = [w = words](){}; // almost like a C# anonymous type
cout << l.w[0]; // does not work. 

解决方案

The status quo

This was discussed when lambda init-captures were added to the language. The current working draft of the standard (N3797) says (in [expr.prim.lambda]p11):

For every init-capture a non-static data member named by the identifier of the init-capture is declared in the closure type.

The standard does not specify the access of that member, making it unclear whether this is valid:

auto x = [n(0)] {};
int k = x.n; // ok?

This and some other specification problems with init-captures led to national body comment GB3 on the standard draft, which is handled by the C++ core working group as core issue 1760. In discussion of that issue, the core working group decided that the lambda's init-captures should not be accessible members of the closure object.

The resolution for issue 1760 (which is approved by CWG but not yet by the full committee) changes the specification to instead say:

An init-capture behaves as if it declares and explicitly captures a variable of the form "auto init-capture ;" whose declarative region is the lambda-expression's compound-statement [...]

This new wording makes it clear that the init-capture does not add a nameable member of the closure object, and it instead acts like any other lambda capture.

As a language extension

Making init-captures be accessible members of the closure type is certainly possible (and my initial implementation of init-captures in clang did that, before I implemented the resolution of issue 1760). It also seems like a useful feature, but it would also allow violation of the encapsulation of lambda-expressions in the common case where the init-captures should not be visible.

这篇关于像struct成员一样访问C ++ 14 lambda捕获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆