Lambda捕获和具有相同名称的参数-谁遮蔽了另一个? (c声与gcc) [英] 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 及更高版本,打印出您正在使用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 及更高版本,打印出您正在使用g ++!" 并警告参数
未使用. g++ 4.9.0 and newer print out "You're using g++!" and warn about the parameter
foo
being unused.在这里,哪种编译器更准确地遵循C ++标准?
What compiler is more accurately following the C++ Standard here?
推荐答案
Update: as promised by the Core chair in the bottom quote, the code is now ill-formed:
如果简单捕获中的标识符作为 lambda-declarator的参数的 declarator-id 出现, /em>的 parameter-declaration-clause ,该程序格式不正确.
If an identifier in a simple-capture appears as the declarator-id of a parameter of the lambda-declarator's parameter-declaration-clause, the program is ill-formed.
前一段时间,有一些关于在lambda中查找名称的问题.它们已通过 N2927 解决:
There were a few issues concerning name lookup in lambdas a while ago. They were resolved by N2927:
新措词不再依赖于查找来重新映射捕获的实体的使用. 更清晰 否认以下解释:lambda的 compound-statement 是在两次处理中处理的,或者该 compound-statement 中的任何名称都可能解析为闭包类型的成员.
The new wording no longer relies on lookup to remap uses of captured entities. It more clearly denies the interpretations that a lambda's compound-statement is processed in two passes or that any names in that compound-statement might resolve to a member of the closure type.
查找总是在 lambda-expression 的上下文中完成的,永远不要转换"到闭包类型的成员函数体之后.参见 [expr.prim.lambda]/8 :>
Lookup is always done in the context of the lambda-expression, never "after" the transformation to a closure type's member function body. See [expr.prim.lambda]/8:
lambda表达式的复合语句产生函数的功能体([dcl.fct.def])调用运算符,但出于名称查找[…]的目的, compound-statement 是在 lambda-expression 的上下文中考虑的. [示例:
The lambda-expression's compound-statement yields the function-body ([dcl.fct.def]) of the function call operator, but for purposes of name lookup, […], the compound-statement is considered in the context of the lambda-expression. [ 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
在嵌套在该外部块中的块中声明(请参见从内部到外部块.因此应该选择该参数,即Clang是正确的.The name
foo
is not (re)declared in the capture; it is declared in the block enclosing the lambda expression. The parameterfoo
is declared in a block that is nested in that outer block (see [basic.scope.block]/2, which also explicitly mentions lambda parameters). The order of lookup is clearly from inner to outer blocks. Hence the parameter should be selected, that is, Clang is right.如果要使捕获成为初始捕获,即
foo = ""
而不是foo
,答案将不清楚.这是因为捕获现在实际上产生了一个声明,该声明的块"没有给出.我就此向核心主席发了信息,谁回答了If you were to make the capture an init-capture, i.e.
foo = ""
instead offoo
, the answer would not be clear. This is because the capture now actually induces a declaration whose "block" is not given. I messaged the core chair on this, who replied这是第2211期(不久之后,新问题列表将显示在open-std.org网站上,很遗憾,其中仅包含占多数的占位符;这是其中的一个;我正在努力填补这些空白在月底的科纳会议之前). CWG在我们一月份的电话会议上对此进行了讨论,如果捕获名称也是参数名称,则方向是使程序格式错误.
这篇关于Lambda捕获和具有相同名称的参数-谁遮蔽了另一个? (c声与gcc)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!