C ++ 20:非类型模板参数中的非捕获lambda [英] C++20: Non-capturing lambda in non-type template parameter
问题描述
C ++ 20是否允许将衰减到函数指针的非捕获lambda作为非类型模板参数直接传递?如果是这样,正确的语法是什么?
Does C++20 allow a non-capturing lambda decayed to a function pointer to be passed directly as a non-type template parameter? If so, what is the correct syntax?
我已经使用 -std = c ++在各种版本的clang和gcc中尝试了以下代码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);
}
gcc编译代码时不会抱怨,并且代码按预期运行。
gcc compiles the code without complaint and the code runs as expected.
clang编译失败,出现以下错误:
clang fails compilation with the following error:
error: a lambda expression cannot appear in this context
using X = S<+[](int x) -> void { std::cout << x << " hello\n"; }>;
^
以下是完整代码(在线版本):
Here is the full code (online versions):
C 10.0.0 HEAD: https://wandbox.org/permlink/n5eKQ4kQqSpDpr4k
Clang 10.0.0 HEAD: https://wandbox.org/permlink/n5eKQ4kQqSpDpr4k
Gcc 10.0.0 HEAD 20200113: https://wandbox.org/permlink/vJ44sdMtwCKAFU64
Gcc 10.0.0 HEAD 20200113: https://wandbox.org/permlink/vJ44sdMtwCKAFU64
推荐答案
使用C + +20是否允许将衰减到函数指针的非捕获lambda直接作为非类型模板参数传递?
Does C++20 allow a non-capturing lambda decayed to a function pointer to be passed directly as a non-type template parameter?
是的。
实际上,您可以再走一步-您甚至不需要将lambda转换为函数指针。您可以只提供lambda。这是有效的C ++ 20:
Indeed, you can go one step further - you don't even need to convert the lambda to a function pointer. You can just provide the lambda. This is valid C++20:
using Y = S<[](int x) -> void { std::cout << x << " hello\n"; }>;
C ++ 20中的规则是现在允许在未评估的上下文中使用lambda( P0315 )。除了那里的许多其他措辞更改外,本文还打破了禁止在模板参数中使用lambda的规则( C ++ 17的[expr.prim.lambda] / 2 ):
The rule we have in C++20 is that lambdas are now allowed in unevaluated contexts (P0315). Among many other wording changes there, this paper struck the rule that prevented lambdas from being used in template arguments (C++17's [expr.prim.lambda]/2):
A lambda-expression 不应出现在未评估的操作数中,在 template-argument 中,在 alias-declaration 中,在typedef声明中,或者在函数主体和默认参数之外的函数或函数模板的声明中。
A lambda-expression shall not appear in an unevaluated operand, in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments.
该子句不在C ++ 20中已经存在了。
That clause does not exist anymore in C++20.
取消此限制,就可以将lambda用作模板参数,并且从无捕获lambda到函数指针的转换在C ++ 17中已经是constexpr了。 clang根本没有实现此功能(使用T = decltype([] {}); ;
在gcc上编译,而在clang上尚未编译)。我不会将其称为clang错误,这只是clang尚未实现的功能(未经评估的上下文中的lambda尚未在 cppreference编译器支持页面)。
Removing this restriction allows the lambda to be used as a template argument, and the conversion from captureless lambda to function pointer was already constexpr in C++17. clang simply does not implement this feature yet (using T = decltype([]{});
compiles on gcc, not yet on clang). I wouldn't call this a clang bug yet, it's just a clang not-yet-implemented-feature (lambdas in unevaluated contexts is not yet listed as implemented in the cppreference compiler support page).
C ++ 20非类型模板参数( P1907 )甚至允许删除 +
,因为无捕获的lambda算作结构类型( temp.param] / 7 ),根本就没有任何数据成员。
C++20 non-type template parameters (P1907) allows even dropping the +
because captureless lambdas count as structural types ([temp.param]/7) by way of simply not having any data members at all.
这篇关于C ++ 20:非类型模板参数中的非捕获lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!