Lambda捕获和参数的同名-谁阴影另一个?(Clangvsgcc)

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (27)
auto foo = "You're using g++!";
auto compiler_detector = [foo](auto foo) { std::puts(foo); };
compiler_detector("You're using clang++!");
  • clang++3.6.0更新打印出来“你用的是clang++!” and warn about the 俘获foo不使用。
  • G++4.9.0更新打印出来“你用的是g++!” and warn about the 参数foo不使用。

哪个编译器在这里更准确地遵循C++标准?

提问于
用户回答回答于

如果标识符在...简单捕获显示为声明符-id的参数的Lambda-声明器参数-声明-子句,这个节目的形式不太好。

新的措辞不再依赖查找来重新映射捕获实体的使用。它更清楚地否认了兰博达的解释复合语句被处理成两次传递,或者其中的任何名称都会被处理。复合语句可能会解析为闭包类型的成员。

查找总是在Lambda表达,永远不要“在”转换为闭包类型的成员函数体之后。

Lambda表达复合语句产生功能体(dcl.fct.def)函数调用操作符,但为了查找名称,复合语句的上下文中考虑到Lambda表达.[* 结构S1{int x,y;int运算符()(Int);void f(){=->int{返回运算符()(this->x+y);//等效于:s1::运算符()(this->x+(*)//这有S1类型。*}}};

名字foo不是在捕获中声明;它是在包含lambda表达式的块中声明的。因此,应该选择参数,即Clang是正确的。

如果你要将捕获变成一个init捕获,即foo = ""而不是foo答案并不明确。

这是第2211期(一个新的问题清单将很快出现在开放的std.org网站上,不幸的是,其中一些问题只有占位符,这是其中之一;我正努力在月底科纳会议之前填补这些空白)。CWG在一月份的电话会议上讨论了这个问题,如果捕获名称也是参数名,则方向是使程序格式不正确。

用户回答回答于

首先,请注意:

  • 每个副本捕获变量的lambda都声明非静态数据成员。
  • 在特定情况下,lambda有一个闭包类型,它有一个公共内联模板函数调用操作符,它接受一个名为foo

因此,逻辑让我乍一看就会说,参数应该将捕获的变量隐藏起来,就像在:

struct Lambda {
    template<typename T> void operator()(T foo) const { /* ... */ }
    private: decltype(outer_foo) foo{outer_foo};
};

无论如何,@nm.正确地注意到,为复制捕获的变量声明的非静态数据成员实际上是未命名的。

正如@nm.在对问题的评论中正确指出的:

最初捕获的实体,应按照范围规则进行正常的阴影处理。

扫码关注云+社区