英文:
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作用域,该作用域从E
的lambda-introducer之后立即开始,一直延伸到E
的compound-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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论