如果我们看一下 草案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);
那么为什么lambdas表达式在未评估的操作数中是不允许的,但是在常量表达式的未评估部分中是允许的?
在几种情况下,我可以看到未评估操作数的类型信息(decltype 要么 typeid的)因为每个lambda都有一个独特的类型,所以并不是很有用。虽然为什么我们希望允许它们在未经评估的不断表达的上下文中,但也不清楚,也许是为了考虑 SFINAE?
核心原因 未经评估的操作数 排除在中 C ++标准核心语言缺陷报告和接受的问题#1607。模板参数中的Lambda 旨在澄清这一限制,并在章节中说明限制的意图 5.1.2
是:
[...]避免在功能模板签名中处理它们的需要[...]
由于问题文件,目前的措辞实际上有一个漏洞 常数表达式 允许他们在未评估的背景下。但它并没有直截了当地说明这种限制的理由。避免名称破坏的愿望脱颖而出,你可以推断避免扩展 SFINAE 由于拟议的决议试图收紧限制,即使有几个可行的替代方案可以允许,也是人们所希望的 SFINAE。修改后的版本 5.1.2
段 2 如下:
lambda表达式不应出现在未评估的操作数中(第5条[expr]), 在模板参数中,在别名声明中,在typedef声明中,或在函数体和默认参数之外的函数或函数模板的声明中[注意:目的是防止lambda出现在签名-end中注意]。 [注意:闭包对象的行为类似于函数对象(20.10 [function.objects])。 - 尾注]
该提案已被接受并且已经提交 N3936
(看到这个答案的链接)
有关避免将lambdas作为一个问题的理由的更明确的讨论 未评估的操作数。讨论标题为 在未评估的上下文中不允许使用lambda表达式的基本原理 在comp.lang.cpp.moderated上 丹尼尔克鲁格勒 列出了三个原因:
该 极端延伸 可能的 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; });
声明和调用中lambda的类型不同(根据定义)因此这不起作用。
名字错误 一旦你允许,也会成为一个问题 拉姆达 在函数签名中的主体 拉姆达 也必须受到损害。这意味着要制定规则以尽可能地破坏 声明对于至少一些实现而言,这将是繁重的。
核心原因 未经评估的操作数 排除在中 C ++标准核心语言缺陷报告和接受的问题#1607。模板参数中的Lambda 旨在澄清这一限制,并在章节中说明限制的意图 5.1.2
是:
[...]避免在功能模板签名中处理它们的需要[...]
由于问题文件,目前的措辞实际上有一个漏洞 常数表达式 允许他们在未评估的背景下。但它并没有直截了当地说明这种限制的理由。避免名称破坏的愿望脱颖而出,你可以推断避免扩展 SFINAE 由于拟议的决议试图收紧限制,即使有几个可行的替代方案可以允许,也是人们所希望的 SFINAE。修改后的版本 5.1.2
段 2 如下:
lambda表达式不应出现在未评估的操作数中(第5条[expr]), 在模板参数中,在别名声明中,在typedef声明中,或在函数体和默认参数之外的函数或函数模板的声明中[注意:目的是防止lambda出现在签名-end中注意]。 [注意:闭包对象的行为类似于函数对象(20.10 [function.objects])。 - 尾注]
该提案已被接受并且已经提交 N3936
(看到这个答案的链接)
有关避免将lambdas作为一个问题的理由的更明确的讨论 未评估的操作数。讨论标题为 在未评估的上下文中不允许使用lambda表达式的基本原理 在comp.lang.cpp.moderated上 丹尼尔克鲁格勒 列出了三个原因:
该 极端延伸 可能的 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; });
声明和调用中lambda的类型不同(根据定义)因此这不起作用。
名字错误 一旦你允许,也会成为一个问题 拉姆达 在函数签名中的主体 拉姆达 也必须受到损害。这意味着要制定规则以尽可能地破坏 声明对于至少一些实现而言,这将是繁重的。