什么时候可以省略C ++ 11 lambda中的返回类型?

时间:2015-03-10 03:05:31

标签: c++ c++11 lambda type-deduction

就I know而言,在标准C ++ 11(而不是C ++ 14 )中,当省略lambda的返回类型时,其返回类型推断为:

  1. 返回表达式的类型,只要lambda只包含带表达式的单个return语句,或者
  2. 在所有其他情况下
  3. void
  4. 现在考虑一下这段代码:

    #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}}。这里发生了什么?我是否解释了标准错误?

3 个答案:

答案 0 :(得分:11)

您的代码在没有任何警告的情况下被接受,因为原始的C ++ 11限制被认为是标准中的缺陷,允许实现修复行为。请参阅CWG DR975DR1048N3638

  

<强> 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