简体   繁体   English

为什么[=] {}有一个lambda捕获?

[英]Why does [=]{} have a lambda capture?

At an intuitive level, it makes sense that a lambda that needs to carry no state (through a reference or otherwise) should be cleanly convertible to a naked function pointer. 在直观的层面上,有意义的是,需要不携带状态(通过引用或其他方式)的lambda应该可以干净地转换为裸函数指针。 However, I was recently surprised to see the following failing in GCC, Clang, and MSVC: 但是,我最近惊讶地看到GCC,Clang和MSVC中的以下失败:

int main(int, char *[]) {
    void (*fp)() = []{}; // OK
  //fp = [=]{};          // XXX - no user defined conversion operator available
  //fp = [&]{};          // XXX - same ...
}

The C++17 spec (or at least visible public draft version N4713 ), refers in item 7 of § 8.4.5.1 [expr.prim.lambda.closure] to lambdas with and without captures: C ++ 17规范(或至少可见的公共草案版本N4713 )在第8.4.5.1节[expr.prim.lambda.closure]的第7项中引用了带有和不带捕获的lambda:

The closure type for a non-generic lambda-expression with no lambda-capture whose constraints (if any) are satisfied has a conversion function to pointer to function with C++ language linkage (10.5) having the same parameter and return types as the closure type's function call operator. 没有lambda-capture的非泛型lambda表达式的闭包类型,其约束(如果有的话)被满足有一个转换函数指向函数,C ++语言链接(10.5)具有与闭包类型相同的参数和返回类型函数调用运算符。 ... ...

However, looking into the formal grammar you can see the following in § 8.4.5 [expr.prim.lambda] : 但是,查看正式语法,您可以在§8.4.5[expr.prim.lambda]中看到以下内容:

  • lambda-expression : lambda表达式
    • lambda-introducer compound-statement lambda-introducer 复合语句
    • ... ...
  • lambda-introducer : lambda介绍人
    • [ lambda-capture opt ] [ lambda-capture opt ]
  • ... ...

and in § 8.4.5.2 [expr.prim.lambda.capture] : 在§8.4.5.2 [expr.prim.lambda.capture]中

  • lambda-capture : lambda-capture
    • capture-default 捕获的默认
    • capture-list 捕捉列表
    • capture-default, capture-list capture-default,capture-list
  • capture-default : capture-default
    • &
    • = =

So all the compilers were actually obeying the letter of the law to my dismay... 因此,所有编制者实际上都遵守了法律条文令我沮丧......

Why does the language define the existence of a capture as a narrow grammatical distinction in the declaration instead of basing it on whether the body contains references to any non-static/captured state? 为什么语言将声明的存在定义为声明中的狭义语法区别,而不是基于主体是否包含对任何非静态/捕获状态的引用?

The change that allowed the conversion was initiated by a national body comment. 允许转换的变化是由国家机构评论发起的。 See n3052: Converting Lambdas to Function Pointers which refers to national body comment UK 42 : 请参阅n3052:将Lambdas转换为功能指针 ,指的是国家机构评论UK 42

A lambda with an empty capture list has identical semantics to a regular function type. 具有空捕获列表的lambda具有与常规函数类型相同的语义。 By requiring this mapping we get an efficient lambda type with a known API that is also compatible with existing operating system and C library functions. 通过要求这种映射,我们得到一个有效的lambda类型,它具有已知的API,也与现有的操作系​​统和C库函数兼容。

and the resolution from N3052 was: N3052的决议是:

Resolution: Add a new paragraph: "A lambda expression with an empty capture set shall be convertible to pointer to function type R(P), where R is the return type and P is the parameter-type-list of the lambda expression." 解决方案:添加一个新段落:“具有空捕获集的lambda表达式应该可转换为指向函数类型R(P)的指针,其中R是返回类型,P是lambda表达式的参数类型列表。” Additionally it might be good to (a) allow conversion to function reference and (b) allow extern "C" function pointer types. 另外,(a)允许转换为函数引用和(b)允许extern“C”函数指针类型可能是好的。

... ...

Add a new paragraph after paragraph 5. The intent of this edit is to obtain a closure-to-function-pointer conversion for a lambda with no lambda-capture. 在第5段之后添加一个新段落。此编辑的目的是获取没有lambda-capture的lambda的闭包到函数指针转换。

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type's function call operator. 没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数。 The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type's function call operator. 此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果。

and that is where we are today. 这就是我们今天所处的位置。 Note the comment said empty capture list and what we have today seems to match the intent as worded in the comment. 请注意,评论说空捕获列表和我们今天所拥有的内容似乎与评论中的措辞相符。

It looks like it was a fix based on a national body comment and was applied narrowly. 它看起来像是基于国家机构评论的解决方案,并且被狭隘地应用。

The rule you propose would be extremely fragile, especially in the pre-P0588R1 world when implicit captures depended on odr-use. 你提出的规则将是非常脆弱的,尤其是在P0588R1之前的世界,当隐式捕获取决于使用odr时。

Consider: 考虑:

void g(int);
void h(const int&);

int my_min(int, int);

void f(int i) {
    const int x = 1, y = i;
    [=]{ g(x); }; // no capture, can convert?
    [=]{ g(y); }; // captures y
    [=]{ h(x); }; // captures x
    [=]{ my_min(x, 0); }; // no capture, can convert?
    [=]{ std::min(x, 0); }; // captures x
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么按副本捕获lambda具有相同的外部变量地址 - Why lambda capture by copy have the same address of an external variable 为什么lambda init-capture不能用于unique_ptr? - Why does lambda init-capture not work for unique_ptr? 为什么 lambda 通过引用捕获仍在使用悬空引用? - Why does lambda capture by reference is still working with dangling references? 为什么lambda的大小为1个字节? - Why does a lambda have a size of 1 byte? =在lambda的捕获列表中是否捕获此指针 - Does = in a capture list of a lambda capture the this pointer 为什么隐含的“lambda to function pointer conversion”禁止静态成员的“by reference”捕获? - Why does the implicit “lambda to function pointer conversion” forbid the “by reference” capture of static members? 为什么访问我的按引用捕获变量会导致我的lambda函数出现段错误? - Why does accessing my capture-by-reference variable cause a segfault in my lambda function? 当我使用[=]捕获(使用Lambda类)时,为什么变量变为'const'? - Why does a variable become 'const' when I use a [=] capture (using Lambda class)? 为什么 C++11 的 lambda 默认情况下需要“可变”关键字用于按值捕获? - Why does C++11's lambda require "mutable" keyword for capture-by-value, by default? 带有std :: function的泛型lambda不捕获变量 - Generic lambda with std::function does not capture variables
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM