Lambda返回Lambda错误地推断返回类型

Lambda returning lambda incorrectly infers return type?

本文关键字:Lambda 返回类型 返回 错误      更新时间:2023-10-16

这个问题是我最近一个问题的延续:
当使用lambda作为模板参数时,这个编译器错误是什么?

11月。2014年11月11日:微软回应说,这个错误的修复应该会在Visual c++的下一个主要版本中出现。


使用VS2012 (Update 2)编译此代码失败:

int main(int argc, char* argv[])
{
    auto f = []()
    {
        int n = 0;
        auto r = [=]{ return n; };
        return r;
    };
    return 0;
}

这是我得到的编译错误:

1>  main.cpp
1>C:testmain.cpp(7): error C2440: 'return' : cannot convert from 'main::<lambda_c5d1d707b91a1ddedc06eb080503550c>::()::<lambda_ac357c309731f4971c3269160ed9c24b>' to 'int (__cdecl *)(void)'
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

  • 根据c++ 11规范的代码有问题吗?
  • 根据VS2012定义的部分c++ 11支持的代码是否有问题?
  • 或者这是VS2012 c++编译器的错误?

  • 有人能告诉我c++ 11规范中关于lambda必须隐式转换为函数指针的地方吗?
    • 我记得这只适用于无状态 lambda -那些具有空捕获子句的lambda -其内部lambda r而不是
    • 那么,为什么看起来lambda f的推断返回类型是一个函数指针,即int (__cdecl *)(void) ?

尽管GCC 4.7.2编译了这段代码,但它是不规范的。初始化f的lambda表达式过于复杂,无法推断返回类型。事实上,5.1.2/4说

如果lambda表达式不包含尾随返回类型,则尾随返回类型表示以下类型:

—如果复合语句的形式为

   { attribute-specifier-seq[opt] return expression ; }

左值到右值转换(4.1)、数组到指针转换(4.2)和函数到指针转换(4.3)后返回表达式的类型;

-否则,无效。

因此,在本例中,返回类型是void,但是lambda返回的是别的东西。该代码不能编译。

我同意Visual Studio给出的信息是误导人的。

Update: On this question

所以说"在c++ 11中,你不能定义一个返回有状态lambda的lambda"是正确的吗?

。根据下面的c++ 11引用,lambda返回的类型是void,除非lambda的主体只包含一行return expression;。因此,如果您设法在返回表达式中创建有状态lambda,那么这是可以的。例如,下面的代码可以在GCC 4.7.2, Clang 3.2和Intel编译器13.1.0中编译:(由于上述错误,它不能在VS2012中编译)

#include <iostream>
int main() {
  int n = 5;
  auto f = [=] {
      return [=]{ return n; }; // creates a stateful lambda and returns it in a single line
  };
  std::cout << f()() << std::endl;
  return 0;
}