显式指定通用 lambda 的 operator() 模板参数是不是合法?

Posted

技术标签:

【中文标题】显式指定通用 lambda 的 operator() 模板参数是不是合法?【英文标题】:Is it legal to explicitly specify a generic lambda's operator() template arguments?显式指定通用 lambda 的 operator() 模板参数是否合法? 【发布时间】:2018-08-29 18:29:32 【问题描述】:

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

#include <iostream>

int main()

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

clang++ 3.8.0g++ 7.2.0 compile this code fine(编译器标志为 -std=c++14 -Wall -Wextra -Werror -pedantic-errors)。

【问题讨论】:

如果你想查,这里有一份标准的here。 AFAIK 确实如此。 lambda 的 operator() 是公开的,所以我看不到任何可以阻止它的东西。 阅读en.cppreference.com/w/cpp/language/lambda。你可以做到的。 我知道您不必在language-lawyer 中给出原因,但出于好奇,您可能希望在哪种情况下给出原因? @SergeyA, template &lt;class From, class To&gt; constexpr To nightmare_cast(From t) return [](auto v)constexpr return v; .operator() &lt; To &gt; (t); 愿诸神原谅我:) 【参考方案1】:

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

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


供参考,相关标准条款:

非泛型 lambda 表达式的闭包类型有一个公共的 内联函数调用运算符(16.5.4),其参数和返回 类型由 lambda 表达式描述 parameter-declaration-clause 和 trailing-return-type 分别。 对于泛型 lambda,闭包类型具有公共内联函数 调用操作员成员模板 (17.5.2),其模板参数列表 由每个出现的一个发明类型模板参数组成 lambda 的参数声明子句中的 auto ,按顺序 外观。发明的类型模板参数是一个参数包 如果相应的参数声明声明了一个函数 参数包 (11.3.5)。返回类型和函数参数 函数调用运算符模板源自 lambda 表达式的尾随返回类型和 parameter-declaration-clause 通过替换每次出现的 auto in 带有名称的参数声明子句的声明说明符 相应发明的模板参数。

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

【讨论】:

【参考方案2】:

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

[expr.prim.lambda]/5

... 对于泛型 lambda,闭包类型具有公共内联函数 调用操作员成员模板 (14.5.2),其 template-parameter-list 由一种发明类型 template-parameter 组成 对于 lambda 的 parameter-declaration-clause 中每次出现的 auto,按出现顺序。 ...

【讨论】:

以上是关于显式指定通用 lambda 的 operator() 模板参数是不是合法?的主要内容,如果未能解决你的问题,请参考以下文章

从通用 lambda 调用 `this` 成员函数 - clang vs gcc

显式原子加载/存储与通常的 operator= 和 operator T 有啥区别?

operator== 和 boost::detail::atomic_count 中的显式构造函数?

为啥允许使用泛型 lambda 而不允许使用带有模板化方法的嵌套结构?

是否可以在C#中定义通用lambda?

Lambda 函数作为基类