Lambda capture and parameter with same name - who shadows the other? (clang vs gcc)

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 and newer print out "You're using clang++!" and warn about the capture foo being unused.

  • g++ 4.9.0 and newer print out "You're using g++!" and warn about the parameter foo being unused.

What compiler is more accurately following the C++ Standard here?

wandbox example

6294 次浏览

我正在努力收集对这个问题的一些意见,以便给你一个有意义的答案。
首先,请注意:

  • 对于每个复制捕获的变量,为 lambda 声明非静态数据成员
  • In the specific case, the lambda has a closure type which has a public inline template function call operator accepting a parameter named foo

因此,这个逻辑会让我在第一眼就说,参数应该隐藏捕获的变量,就好像在:

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

不管怎样。正确地注意到,为拷贝捕获变量声明的非静态数据成员实际上是未命名的。也就是说,仍然可以通过标识符(即 foo)访问未命名的数据成员。因此,函数调用操作符的参数名应该仍然是(让我说) shadow that identifier
正如@n. m. 在对问题的评论中正确指出的:

原始捕获的实体[ ... ]应根据作用域规则正常隐藏

正因为如此,我认为那声音是对的。

更新: 正如核心主席在底部引用中所承诺的,代码是 现在变形了:

如果 简单捕捉中的一个 标识符作为 Lambda-声明器参数-声明-子句的一个参数的 声明程序 ID出现,那么程序就是病态的。


前段时间在 lambdas 中出现了一些与名称查找有关的问题,N2927解决了这些问题:

新的措辞不再依赖于查找来重新映射被捕获实体的使用 否认对 lambda 的 compound-statement在两次传递中处理的解释,或者该 compound-statement中的任何名称可能解析为闭包类型的成员。

查找总是在 Lambda 表情的上下文中进行,从不“在”转换为闭包类型的成员函数体之后进行。见 [ expr.prim.lambda ]/8:

Lambda 表情复合陈述产生函数调用操作符的 功能体([ dcl.fct.def ]) ,但是为了名称查找的目的,[ ... ] ,复合陈述被考虑在 Lambda 表情的上下文中。[ Example:

struct S1 {
int x, y;
int operator()(int);
void f() {
[=]()->int {
return operator()(this->x+y);  // equivalent to: S1::operator()(this->x+(*this).y)
// and this has type S1*
};
}
};

最后一个例子]

(这个示例还清楚地表明,查找不会以某种方式考虑生成的闭包类型的捕获成员。)

名称 foo不是在捕获中(重新)声明的; 它是在包含 lambda 表达式的块中声明的。参数 foo在嵌套在外部块中的块中声明(参见 [ basic.scope.block ]/2,它也明确提到了 lambda 参数)。查找的顺序显然是 从内层到外层。因此应该选择参数,也就是说,Clang 是正确的。

如果您将捕获设置为 init 捕获,即 foo = ""而不是 foo,那么答案将是不清楚的。这是因为捕获现在实际上是 诱发一个声明,它的“块”没有给出。我给核心主席发了信息,他回复了

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