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

时间:2014-01-27 20:08:29

标签: 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. 

2 个答案:

答案 0 :(得分:17)

现状

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

  

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

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

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 &#39 ; s 复合语句 [...]

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

作为语言扩展

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

答案 1 :(得分:5)

如果我理解这一点,您希望能够访问在lambda中捕获的变量。但根据Get captured variables from lambda?的最佳答案,这是不可能的。

  

设计

是不可能的      
    

5.1.2 [expr.prim.lambda]

         

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

         

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

  
     

捕获的变量是未命名的(或至少具有名称   凡人无法形容的)他们的声明令是故意的   不确定的。关闭中的引用捕获甚至可能不存在   类型。

大胆强调我的。