就I know而言,在标准C ++ 11(而不是C ++ 14 )中,当省略lambda的返回类型时,其返回类型推断为:
void
。现在考虑一下这段代码:
#include <iostream>
auto closure = [](int x)
{
x++;
return x;
};
int main()
{
int y = closure(10);
std::cout << y << std::endl;
}
这应该属于案例2.但是代码编译好像是带有auto
类型推导的C ++ 14,在g ++ 4.9.2,g ++ 5和clang ++中,{{{ 1}}。这里发生了什么?我是否解释了标准错误?
答案 0 :(得分:11)
您的代码在没有任何警告的情况下被接受,因为原始的C ++ 11限制被认为是标准中的缺陷,允许实现修复行为。请参阅CWG DR975,DR1048和N3638。
<强> 975。对lambdas的退货类型扣除的限制
[作为论文N3638的一部分,在2013年4月的会议上移至灾难恢复状态。]
似乎没有任何技术上的困难需要当前的限制,即只有当lambda的主体由单个return语句组成时,才能推导出lambda的返回类型。特别是,如果它们都返回相同的类型,则可以允许多个return语句。
<强> 1048。自动扣除和lambda返回类型扣除。
...
2014年11月会议的说明:
CWG同意, N3638中所体现的变更应被视为针对C ++ 11的DR 。
总之,DR975建议修改lambda表达式的返回类型推导规则,以允许多个return语句。
DR1048确定了一个差异,其中使用占位符类型auto
推断正常函数的返回类型的规则与DR975中提出的规则略有不同。具体来说,正常函数的返回类型推导会在所有情况下丢弃顶级cv限定符,而lambda表达式的返回类型将保留类类型的cv限定符。
N3638解决了这个问题,等等。
我怀疑有没有办法恢复原来的行为,而不是在上面实施DR之前找到C ++ 11 lambda支持附带的编译器版本。
答案 1 :(得分:3)
一些C ++ 14规则在C ++ 11模式下可用,当编译器编写者认为它太复杂而不能同时实现这两个规则时。
答案 2 :(得分:2)
这是我在C ++草案标准N3337中找到的:
如果 lambda-expression 不包含 lambda-declarator ,那就好像 lambda-declarator 是()。如果 lambda-expression 不包含 trailing-return-type ,就好像 trailing-return-type 表示以下类型:
- 如果复合语句的格式为
{ attribute-specifier-seq opt
return
表达; }lvalue-to-rvalue转换(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
。