我们什么时候可以省略 C++11 lambda 中的返回类型
When can we omit the return type in a C++11 lambda?
我所知,在标准 C++11(不是 C++14)中,当省略 lambda 的返回类型时,其返回类型被推导出为:
- 返回表达式的类型,只要 lambda 只包含一个带有表达式的 return 语句,或者
-
void
在所有其他情况下。
现在考虑以下代码:
#include <iostream>
auto closure = [](int x)
{
x++;
return x;
};
int main()
{
int y = closure(10);
std::cout << y << std::endl;
}
这应该属于情况 2.,但是代码编译为C++14 auto
类型推导,在 g++4.9.2、g++5 和 clang++ 中,带有 -pedantic -Wall -Wextra -std=c++11
。这是怎么回事?我解释标准是错误的吗?
您的代码在没有任何警告的情况下被接受,因为原始的 C++11 限制被视为标准中的缺陷,这允许实现修复行为。请参见CWG DR975、DR1048和N3638。
975.λ返回类型扣除的限制
[在 2013 年 4 月的会议上作为文件 N3638 的一部分移至 DR 状态。
似乎没有任何技术困难需要当前的限制,即只有当 lambda 的主体由单个返回语句组成时,才能推断出 lambda 的返回类型。特别是,如果多个 return 语句都返回相同的类型,则可以允许它们。
1048.自动演绎和λ返航型演绎。
。
2014年11月会议记录:
CWG同意,文件N3638中体现的变化应被视为针对C++11的DR。
总之,DR975 建议修改 lambda 表达式的返回类型推导规则,以允许多个返回语句。
DR1048 标识了一个差异,其中使用占位符类型推断正常函数返回类型的规则与 DR975 中提出的规则略有不同auto
。具体来说,普通函数的返回类型推导在所有情况下都会丢弃顶级 cv 限定符,而 lambda 表达式的返回类型推导将保留类类型的 cv 限定符。
N3638 解决了此问题等。
<小时 />我怀疑除了在实现上述 DR 之前找到附带 C++11 lambda 支持的编译器版本之外,有什么方法可以恢复到原始行为。
C++14 规则在 C++11 模式下可用,当编译器编写者认为同时实现这两个规则太复杂时。
在C++草案标准N3337中找到的:
如果 lambda 表达式不包含 lambda 声明符,则 lambda 声明符就像 () 一样。如果 lambda 表达式不包含尾随返回类型,则尾随返回类型表示以下类型:
— 如果复合语句的形式是
{ 属性说明符-seqopt
左值到return
表达式 ; }右值转换 (4.1)、数组到指针转换 (4.2) 和函数到指针转换 (4.3) 后返回的表达式的类型;
— 否则,
void
.[ 示例:
auto x1 = [](int i){ return i; }; // OK: return type is int auto x2 = []{ return { 1, 2 }; }; // error: the return type is void (a // braced-init-list is not an expression)
— 结束示例 ]
该标准似乎表明:
- 当只有一个语句存在时,并且
- 这是一个返回语句,并且
- 返回的对象是一个表达式
然后从表达式中推导出返回类型。否则,返回类型为 void
。
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- 如何推导lambda的返回类型
- 尽管显式声明了返回类型,但对lambda的调用是不明确的
- 是否创建具有不同返回类型的lambda
- 防止 lambda 的返回类型扣除
- 我可以让返回类型自动处理具有相同签名但捕获不同内容的 lambda 吗?
- 如何通过返回类型区分两个 lambda 函数?
- 如何在C++中比较 lambda 函数的返回类型?
- 获取模板函数/泛型 lambda 的唯一返回类型
- Spirit.X3 与 lambda 返回不同的解析器类型
- 尝试使用具有尾随返回类型的 lambda 进行 SFINAE 时出现硬错误
- 具有尾随返回类型的通用 lambda,具体取决于 C++11 中的可变参数
- IF-ELSE语句的Lambda表达式的返回类型扣除
- 在 C++14 中使用通用 lambda 和自动返回类型特征获得不同的结果
- 尝试传递 constexpr lambda 并使用它来显式指定返回类型
- 如何用clang格式分隔lambda的尾部返回类型
- C++11对lambda返回类型的限制
- 编译器警告:无法推导lambda返回类型
- 是我的书吗;s对lambda返回类型的讨论是错误的