其他分享
首页 > 其他分享> > c – 为什么在未评估的操作数中不允许使用lambda表达式,但是在常量表达式的未评估部分中允许使用lambda表达式?

c – 为什么在未评估的操作数中不允许使用lambda表达式,但是在常量表达式的未评估部分中允许使用lambda表达式?

作者:互联网

如果我们看一下draft C++ standard部分5.1.2 Lambda表达式第2段说(强调我的前进):

The evaluation of a lambda-expression results in a prvalue temporary (12.2). This temporary is called the closure object. A lambda-expression shall not appear in an unevaluated operand (Clause 5). [ Note: A closure object behaves like a function object (20.8).—end note ]

第5.19节常数表达第2段说:

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered […]

并有以下子弹:

— a lambda-expression (5.1.2);

那么为什么lambda表达式不允许在未评估的操作数中,但是在常量表达式的未评估部分中是允许的?

我可以看到,对于未评估的操作数,在几种情况下(decltypetypeid)的类型信息不是很有用,因为每个lambda都有一个唯一的类型.虽然我们为什么要在未评估的情况下允许它们在一个不变的表达式中不清楚,也许是为了允许SFINAE

解决方法:

C++ Standard Core Language Defect Reports and Accepted Issues #1607. Lambdas in template parameters涵盖了未评估的操作数排除的核心原因,该目的旨在澄清这一限制,并指出第5.1.2节中限制的意图是:

[…] avert the need to deal with them in function template signatures […]

由于问题文件,当前的措辞实际上有一个漏洞,因为常量表达式允许它们在未评估的上下文中.但它没有直截了当地说明这种限制的理由.避免名称损失的愿望脱颖而出,你可以推断,避免延长SFINAE也是可取的,因为提议的决议旨在收紧限制,即使有几个可行的替代方案允许SFINAE. 5.1.2第2段的修改版如下:

A lambda-expression shall not appear in an unevaluated operand (Clause 5 [expr]), 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 [Note: The intention is to prevent lambdas from appearing in a signature —end note]. [Note: A closure object behaves like a function object (20.10 [function.objects]). —end note]

此提案已被接受,并在N3936(see this answer for a link)

有关避免将lambda作为未评估操作数的基本原理的更明确的讨论. comp.lang.cpp.moderated上的题为Rationale for lambda-expressions not being allowed in unevaluated contexts的讨论DanielKrügler提出了三个原因:

>可能SFINAE案件的极端延伸:

[…]The reason why they became excluded was due to exactly this extreme extension of sfinae cases (you were opening a Pandora box for the compiler)[…]

>在许多情况下它只是没用,因为每个lambda都有一个独特的类型,给出了一个假设的例子:

template<typename T, typename U>
void g(T, U, decltype([](T x, T y) { return x + y; }) func);

g(1, 2, [](int x, int y) { return x + y; });

声明和调用中lambda的类型是不同的(根据定义),因此这不起作用.
> Name mangling也成为一个问题,因为一旦你在函数签名中允许lambda,lambda的主体也必须被修复.这意味着要制定规则来破坏每一个可能的陈述,这对于至少一些实现来说会很麻烦.

标签:constant-expression,c,c11,lambda,c14
来源: https://codeday.me/bug/20190923/1813692.html