18

是否符合以下 C++ 代码标准?

#include <iostream>

int main()
{
    [](auto v){ std::cout << v << std::endl; }.operator()<int>(42);
}

clang++ 3.8.0g++ 7.2.0可以很好地编译这段代码(编译器标志是-std=c++14 -Wall -Wextra -Werror -pedantic-errors)。

4

2 回答 2

17

这确实符合标准。该标准规定必须有一个成员operator(),并且它auto的参数声明子句中的每次出现都有一个模板参数。没有任何文字明确禁止提供这些内容。

底线:lambda 的调用运算符只是一个普通函数(模板,如果是通用的)。


供参考,相关标准条款:

非泛型 lambda 表达式的闭包类型具有公共内联函数调用运算符 (16.5.4),其参数和返回类型分别由 lambda 表达式的参数声明子句和尾随返回类型描述。 对于泛型 lambda,闭包类型有一个公共内联函数调用运算符成员模板 (17.5.2),其模板参数列表由一个发明的类型模板参数组成,用于 lambda 的参数声明子句中每次出现的 auto,按出场顺序。如果相应的参数声明声明了函数参数包(11.3.5),则发明的类型模板参数是参数包。函数调用运算符模板的返回类型和函数参数派生自 lambda 表达式的尾随返回类型和参数声明子句,方法是将参数声明子句的 decl 说明符中的每次出现 auto 替换为相应发明的模板参数的名称。

N4659 (C++17) 中的 8.1.5.1/3 [expr.prim.lambda.closure],强调我的。

于 2018-03-20T19:41:50.483 回答
13

是的,它似乎定义明确,因为 lambdas 的模板参数operator()是严格定义的。

[expr.prim.lambda]/5

...
对于通用 lambda,闭包类型具有公共内联函数调用运算符成员模板(14.5.2),其模板参数列表由一个发明的类型模板参数auto组成,用于lambda 的参数声明中的 每次出现子句,按出现顺序。
...

于 2018-03-20T19:41:22.320 回答