Ros*_*ina 10 c++ lambda templates c++20
C++20 是否允许衰减为函数指针的非捕获 lambda 直接作为非类型模板参数传递?如果是这样,正确的语法是什么?
我已经在各种版本的 clang 和 gcc 中使用-std=c++2a.
#include <iostream>
template<auto f>
struct S {
static void invoke(int x) { f(x); }
};
using X = S<+[](int x) -> void { std::cout << x << " hello\n"; }>;
int main()
{
X::invoke(42);
}
Run Code Online (Sandbox Code Playgroud)
gcc 毫无怨言地编译代码,代码按预期运行。
clang 编译失败并出现以下错误:
error: a lambda expression cannot appear in this context
using X = S<+[](int x) -> void { std::cout << x << " hello\n"; }>;
^
Run Code Online (Sandbox Code Playgroud)
这是完整的代码(在线版本):
Clang 10.0.0 头:https : //wandbox.org/permlink/n5eKQ4kQqSpDpr4k
Gcc 10.0.0 HEAD 20200113:https ://wandbox.org/permlink/vJ44sdMtwCKAFU64
Bar*_*rry 11
C++20 是否允许衰减为函数指针的非捕获 lambda 直接作为非类型模板参数传递?
是的。
事实上,您可以更进一步——您甚至不需要将 lambda 转换为函数指针。您可以只提供 lambda。这是有效的 C++20:
using Y = S<[](int x) -> void { std::cout << x << " hello\n"; }>;
Run Code Online (Sandbox Code Playgroud)
我们在 C++20 中的规则是现在允许在未评估的上下文中使用 lambdas ( P0315 )。在那里的许多其他措辞更改中,本文打破了阻止 lambda 在模板参数中使用的规则(C++17 的 [expr.prim.lambda]/2):
一个拉姆达表达式不得出现在未计算的操作,在一个模板参数,在一个别名声明,在typedef声明,或在外面的函数体和默认参数的函数或函数模板的声明。
该子句在 C++20 中不再存在。
取消这个限制允许将 lambda 用作模板参数,并且从无捕获 lambda 到函数指针的转换在 C++17 中已经是 constexpr。clang 还没有实现这个特性(using T = decltype([]{});在 gcc 上编译,还没有在 clang 上编译)。我还不会称其为 clang 错误,它只是一个尚未实现的 clang 功能(未评估上下文中的 lambdas 尚未在cppreference 编译器支持页面中列出为已实现)。
C++20 非类型模板参数 ( P1907 ) 甚至允许通过根本没有任何数据成员的方式删除+因为无捕获的 lambda 算作结构类型( [temp.param]/7 )。