为什么在 lambda 表达式的参数声明子句中查找名称时找不到 init-captures?

huangapple go评论75阅读模式
英文:

Why does name lookup in the parameter-declaration-clause of a lambda expression not find init-captures?

问题

我测试了Godbolt上的3个编译器,它们都拒绝了这个代码,因为不能对指针应用一元减号。

然而,我无法弄清楚标准为什么要求这种行为。根据[expr.prim.lambda.capture]/6的规定:

init-capture存在于lambda-expression的lambda作用域中([basic.scope.lambda])...。

lambda作用域在[basic.scope.lambda]中定义:

lambda-expression E引入了一个lambda作用域,该作用域从Elambda-introducer之后立即开始,一直延伸到Ecompound-statement的末尾。

lambda-introducer是被包含在方括号内的部分,因此在[x = 1]的闭合方括号之后,对于x的名称查找应该立即开始查找init-capture,而不是查找在封闭块作用域中声明的变量x

但根据编译器的说法,在parameter-declaration-clause中,对于x的名称查找并没有找到init-capture。我确信它们是正确的,我的推理中存在某些问题,但是问题出在哪里呢?

英文:

Consider this example

int main() {
    const char* x;
    [x = 1] (decltype(-x) y) {};
}

I tested 3 compilers on Godbolt and they all reject this because you can't apply unary minus to a pointer.

I can't figure out why the standard requires this behaviour, though. According to [expr.prim.lambda.capture]/6,

> An init-capture inhabits the lambda scope ([basic.scope.lambda]) of the lambda-expression. [...]

The lambda scope is defined in [basic.scope.lambda]:

> A lambda-expression E introduces a lambda scope that starts immediately after the lambda-introducer of E and extends to the end of the compound-statement of E.

The lambda-introducer is the part that's enclosed in square brackets, so it would appear that immediately after the closing square bracket in [x = 1], name lookup for x should begin to find the init-capture and not the variable x declared in the enclosing block scope.

But according to the compilers, while we're still in the parameter-declaration-clause, name lookup for x doesn't find the init-capture. I'm sure they're right and there's something wrong with my reasoning, but what is it?

答案1

得分: 4

The C++ draft on eel.is is newer than C++20. In C++23, the code you've written will (probably) be allowed. There is in fact an example on eel.is that is very similar to yours (decltype of init-capture in the region before the opening {):

auto counter = [i=0]() mutable -> decltype(i) {     // OK, returns int
  return i++;
};

However, all the compilers currently fail to compile this example, just as they fail to compile yours. This is because, in C++20 (or, the closest draft I can find online), the relevant section (draft N4868, [expr.prim.lambda.capture]/6) actually reads (emphasis mine):

An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form auto init-capture ; whose declarative region is the lambda-expression's compound-statement, ...

I.e. the init-captures are indeed only in scope for the body, and not for the parameter declarations or return type. So your code is invalid C++20 but will probably be valid C++23.

英文:

The C++ draft on eel.is is newer than C++20. In C++23, the code you've written will (probably) be allowed. There is in fact an example on eel.is that is very similar to yours (decltype of init-capture in region before the opening {)

auto counter = [i=0]() mutable -> decltype(i) {     // OK, returns int
  return i++;
};

However, all the compilers currently fail to compile this example, just as they fail to compile yours. This is because, in C++20 (or, the closest draft I can find online), the relevant section (draft N4868, [expr.prim.lambda.capture]/6) actually reads (emphasis mine):

> An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form <code>auto <em>init-capture</em> ;</code> whose declarative region is the lambda-expression's compound-statement, ...

I.e. the init-captures are indeed only in scope for the body, and not for the parameter declarations or return type. So your code is invalid C++20 but will probably be valid C++23.

答案2

得分: 1

这是一个在DR中获得批准的C++23功能。
它由clang实现,并应该在clang 17中发布。
相关文件链接为https://wg21.link/P2036R3和https://wg21.link/P2579R0。
1: https://godbolt.org/z/7nf635PnM

英文:

This is a C++23 feature that was approved as a DR.
It is implemented by clang and should ship in clang 17.

The relevant papers are https://wg21.link/P2036R3 and https://wg21.link/P2579R0

huangapple
  • 本文由 发表于 2023年6月8日 09:49:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76428103.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定