Sha*_*our 14 c++ lambda constant-expression c++11 c++14
如果我们看看草案C++标准部分5.1.2 Lambda表达式第2段说(强调我的未来):
lambda表达式的评估导致prvalue临时(12.2).这个临时对象称为闭包对象.lambda表达式不应出现在未评估的操作数中(第5条).[注意:闭包对象的行为类似于函数对象(20.8).-结束注释]
和部分5.19 常量表达式第2段说:
条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不被视为 [...]
并有以下子弹:
- lambda表达式(5.1.2);
那么为什么lambda表达式不允许在未评估的操作数中,但是在常量表达式的未评估部分中是允许的?
我可以看到,对于未评估的操作数,在几种情况下(decltype或typeid)的类型信息不是很有用,因为每个lambda都有一个唯一的类型.虽然为什么我们想要让它们在未经评估的不断表达的背景下不明确,或许是为了让SFINAE?
Sha*_*our 18
C++标准核心语言缺陷报告和已接受的问题#1607涵盖了未评估操作数排除的核心原因.模板参数中的Lambdas试图澄清这一限制并在章节5.1.2中说明限制的意图是:
[...]避免在功能模板签名中处理它们的需要[...]
由于问题文件,当前的措辞实际上有一个漏洞,因为常量表达式允许它们在未评估的上下文中.但它没有直截了当地说明这种限制的理由.避免名称损失的愿望脱颖而出,你可以推断,避免延长SFINAE也是可取的,因为提议的决议旨在收紧限制,即使有几个可行的替代方案允许SFINAE.5.1.2第2款的修改版如下:
lambda表达式不应出现在未评估的操作数(第5条[expr]),模板参数,别名声明,typedef声明或函数体外的函数或函数模板的声明中.和默认参数[注意:目的是防止lambda出现在签名-end note中].[注意:闭包对象的行为类似于函数对象(20.10 [function.objects]). - 尾注]
此提案已被接受并且已经提交N3936(请参阅此答案以获取链接)
有关避免将lambda作为未评估操作数的基本原理的更明确的讨论.关于lambda表达式的基本原理的讨论在comp.lang.cpp.moderated上的未评估上下文中是不允许的,DanielKrügler提出了三个原因:
可能的SFINAE案件的极端扩展:
[...]他们被排除在外的原因是由于sfinae案件的这种极端扩展(你正在为编译器打开潘多拉盒子)[...]
在许多情况下它只是没用,因为每个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; });
Run Code Online (Sandbox Code Playgroud)
声明和调用中lambda的类型是不同的(根据定义),因此这不起作用.
名字改编因为一旦你允许也成为一个问题拉姆达在函数签名的机构拉姆达将不得不以及错位.这意味着要制定规则来破坏每一个可能的陈述,这对于至少一些实现来说会很麻烦.