Access C++ 14 lambda捕获类似struct成员

Sum*_*ant 10 c++ lambda capture c++14

AFAIK,C++ 11/14在定义lambda时不允许就地定义新的返回类型.但是,似乎C++ 14 lambda捕获表达式实际上创建了一个带有一个或多个"成员"和一个operator()的匿名类型.那么,为什么编译器不允许从lambda 外部访问捕获的成员.我的软弱无法处理C++的复杂性,但它听起来像是一种合理的语言扩展吗?这是一个例子.

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

Ric*_*ith 17

现状

将lambda init-capture添加到语言时讨论了这个问题.该标准的当前工作草案(N3797)说(在[expr.prim.lambda] p11中):

对于每个init-capture,在闭包类型中声明由init-capture标识符命名的非静态数据成员.

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

auto x = [n(0)] {};
int k = x.n; // ok?
Run Code Online (Sandbox Code Playgroud)

初始捕获的这个和其他一些规范问题导致国家机构评论标准草案GB3,由C++核心工作组作为核心问题1760处理.在这个问题的讨论,核心工作组决定,拉姆达的初始化,捕获应该不会是关闭对象的可访问成员.

第1760期(由CWG批准但尚未由整个委员会批准)的决议改变了规范,改为:

一个INIT-捕获的行为就好像它声明和明确地捕获形式的可变“auto init-capture ;”其声明性区域是λ-表达化合物语句 [...]

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

作为语言扩展

使init-capture成为闭包类型的可访问成员当然是可能的(在我实现第1760期的解决方案之前,我在clang中初始实现init- capture).它似乎也是一个有用的功能,但它也允许在不应该看到init-capture的常见情况下违反lambda表达式的封装.


小智 5

如果我理解这一点,你希望能够访问在lambda中捕获的变量.但根据从lambda获取捕获变量的最佳答案, 这是不可能的.

这是不可能的设计

5.1.2 [expr.prim.lambda]

15 [...]对于由副本捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员.这些成员的声明顺序未指定.[...]

16 [...]未指定是否在闭包类型中为通过引用捕获的实体声明了其他未命名的非静态数据成员.

捕获的变量是未命名的(或至少具有凡人无法形容的名称),并且故意未指定其声明顺序.封闭类型中甚至可能不存在引用捕获.

大胆强调我的.

  • 正如我在引用的答案中所说,你真的不想那样,你只想到你这样做.支持您想要的内容会限制实现并阻止优化.如果要访问命名成员,那么**不要使用lambda表达式!** (4认同)