编译器警告:无法推断lambda返回类型

时间:2011-12-20 22:08:00

标签: c++ lambda c++11 compiler-warnings

考虑这个例子:

#include <algorithm>
#include <iostream>

int main()
{
    std::string str = "abcde4fghijk4l5mnopqrs6t8uvwxyz";
    std::string str2;

    std::remove_copy_if(str.begin(), str.end(),
        std::back_inserter(str2),
        [](char& c) {
            if (std::isdigit(c))
                return true;      // <----- warning here
            else
                return false;
        }
    );

    std::cout << str2 << '\n';
}

使用GCC 4.6.1,这可以很好地编译并打印预期输出(字母表),但是我得到一个警告说“只有当return语句是函数体中唯一的语句时,才能推断出lambda返回类型”

现在,我知道如何摆脱警告(使用尾随返回类型或只是简单地说return isdigit(c);),但我很好奇,因为编译器没有任何警告(或者应该是这样) :像这样的代码可能出错?标准是否对此有所说明?

2 个答案:

答案 0 :(得分:5)

正如@ildjarn在评论中所说,根据标准,你的代码根本就是不正确的。

§5.1.2 [expr.prim.lambda] p4

  

[...]如果 lambda-expression 不包含 trailing-return-type ,就好像 trailing-return-type 表示以下类型:

     
      
  • 如果复合语句的格式为
      { attribute-specifier-seq opt return expression ; }
      lvalue-to-rvalue转换(4.1),数组到指针转换后返回表达式的类型   (4.2),和函数到指针的转换(4.3);
  •   
  • 否则,void
  •   
     

[...]

就是这样,基本上如果大括号内的代码(在标准中称为 compund-statement )除了return some_expr;之外的任何东西,标准说返回类型是不可约的,你得到void返回类型。

答案 1 :(得分:3)

值得注意的是,这个问题已在C ++ 14中得到纠正。该语言现在正确地推断出OP预期的返回类型。从标准草案[7.1.6.4.11]:

  

如果需要具有未减少占位符类型的实体的类型   为了确定表达式的类型,程序是不正确的。   但是,一旦在函数中看到了return语句,那么   从该语句推导出的返回类型可以在其余部分中使用   函数,包括在其他return语句中。 [例如:

auto n = n; // error, n’s type is unknown
auto f();
void g() { &f; } // error, f’s return type is unknown
auto sum(int i) {
if (i == 1)
    return i; // sum’s return type is int
else
    return sum(i-1)+i; // OK, sum’s return type has been deduced
}
     

-end example]