2017-09-26 249 views
3

之前,你扔烂番茄为什么lambda表达式的捕获列表不能使用结构化绑定分解

我知道的λ分解的实际应用目前仅限 作为一个将无法找到替代故障友好的方式来检查 隐藏在分解变量中的lambda捕获的数量。这只是一个理论问题,因为我没有找到任何涵盖捕获成员变量访问修饰符的标准部分。

int main() { 
    int a; 
    auto [x] = [a]{}; 
    static_cast<void>(a); 
    static_cast<void>(x); 
    return 0; 
} 

标准参考

标准的部分约lambda capture相当长,所以我可能会错过相关的片段。我注意到的是,强调与捕获相对应的非静态成员必须是未命名的。

+0

我真的不明白'auto [x] = [a] {};'的用途是什么。你想在那里做什么? 'x'会是什么? –

+0

@Someprogrammerdude我认为lambda表达式是一个包含来自lambda捕获的状态的内联类定义。普通结构的状态可以绑定到结构绑定变量中。我只是好奇,有没有一种方法可以在这个意义上使用lambda作为普通结构。 –

+0

@Someprogrammerdude我认为'auto [x] = [a] {};''x'会对应'a'。 –

回答

3

我想说这是标准没有说明的,但肯定是无法工作的。我们对lambda结构知道的是,从[expr.prim.lambda.closure]:

lambda表达式(也是闭包对象的类型)的类型是唯一的,未命名的非-union类类型

闭合类型不是一个聚合类型

和,从[expr.prim.lambda.captu re]:

对于通过复制捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员。这些成员的声明顺序是未指定的。

和:

它是未指定的附加的未命名的非静态数据成员是否在闭合类型用于通过参考所捕获实体声明。如果声明,这些非静态数据成员应该是字面类型。

具有未命名成员的意图是避免让它们在lambda体外被访问。这些成员额外处于未指定顺序的后果意味着只要有多个副本捕获,您甚至无法知道您的结构化绑定是干什么的。

int a=1, b=2; 
auto [x, y] = [a, b]{}; // x==1 or x==2?? 

捕获通过引用不一定命名成员的后果意味着,你甚至不知道有多少标识符在结构化约束力的声明列出。

由于非静态数据成员的访问是未指定的,因此可以让一致性实现使它们全部公开,这将满足结构化绑定的情况3。但是这非常违背了lambda表达式的结构以及结构化绑定应该如何工作的意图,所以如果任何实现明确地做到这一点,我会感到惊讶。 gcc,例如,explicitly patched禁止它。