C ++ 20:非类型模板参数中的非捕获lambda [英] C++20: Non-capturing lambda in non-type template parameter

查看:112
本文介绍了C ++ 20:非类型模板参数中的非捕获lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆