直观上来看,一个不需要携带状态(通过引用或其他方式)的 lambda 函数应该可以干净地转换为裸函数指针。然而,我最近惊讶地看到以下代码在 GCC、Clang 和 MSVC 上失败:
int main(int, char *[]) {
void (*fp)() = []{}; // OK
//fp = [=]{}; // XXX - no user defined conversion operator available
//fp = [&]{}; // XXX - same ...
}
C++17规范(或至少可见公共草案版本N4713)在§ 8.4.5.1的第7项中提到了有捕获和无捕获的lambda表达式:对于没有lambda-capture约束条件被满足的非泛型lambda-expression,其闭包类型具有转换函数,可以转换为具有与闭包类型的函数调用运算符相同的参数和返回类型的C ++语言链接函数指针。然而,在正式语法中,您可以在§ 8.4.5 [expr.prim.lambda] 看到以下内容:lambda-expression: lambda-introducer compound-statement ... lambda-introducer:[lambda-captureopt] ...以及在§ 8.4.5.2 [expr.prim.lambda.capture] 中:
- lambda-capture :
- capture-default : 捕获默认值
- capture-list : 捕获列表
- capture-default, capture-list : 捕获默认值和捕获列表
- capture-default :
- & : 引用捕获
- = : 值捕获
所以所有编译器都遵守了法律条文,令我失望...
为什么这种存在于声明中的狭隘语法区别而不是基于函数体是否包含对任何非静态/捕获状态的引用来定义捕获呢?
[=]
和[&]
没有捕获fp
,但它们确实捕获了。 - David Gfp
,当它在函数体中没有被使用? - Igor Tandetnik