C++ Lambda返回Lambda错误地推断返回类型?

C++ Lambda返回Lambda错误地推断返回类型?,c++,visual-studio-2012,compiler-construction,c++11,lambda,C++,Visual Studio 2012,Compiler Construction,C++11,Lambda,这个问题是我最近一个问题的延续: 2014年11月11日:微软回应说,这个bug的修复应该出现在Visual C++的下一个主要版本。 使用VS2012(更新2)无法编译此代码: 这是我得到的编译器错误: 1> main.cpp 1>C:\test\main.cpp(7): error C2440: 'return' : cannot convert from 'main::<lambda_c5d1d707b91a1ddedc06eb080503550c>::(

这个问题是我最近一个问题的延续:

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


使用VS2012(更新2)无法编译此代码:


这是我得到的编译器错误:

1>  main.cpp
1>C:\test\main.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
1>main.cpp
1> C:\test\main.cpp(7):错误C2440:“return”:无法从“main::::”转换为“int(u cdecl*)(void)”
1> 没有可执行此转换的用户定义的转换运算符,或者无法调用该运算符

  • 根据C++11规范,代码有问题吗
  • 根据VS2012定义的部分C++11支持,代码是否存在问题
  • 还是这是VS2012 C++编译器bug?< /LI>

  • 有人能告诉我在C++11规范中提到lambda如何隐式可转换为函数指针的地方吗?
    • 我记得这只适用于无状态lambda(那些具有空捕获子句的lambda),而内部lambda
      r
      不是
    • 那么,为什么lambda
      f
      的推断返回类型似乎是一个函数指针,即
      int(uu 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提供的信息具有误导性

更新:关于这个问题


那么说“在C++11中,不能定义返回有状态lambda的lambda”是否正确

否。根据下面的C++11引号,lambda返回的类型是
void
,除非lambda的主体仅包含一行
返回表达式。因此,如果您设法在返回表达式中创建有状态lambda,那么这就可以了。例如,下面的代码在GCC 4.7.2、Clang 3.2和Intel compiler 13.1.0中编译:(由于前面提到的错误,它没有在VS2012中编译。)

#包括
int main(){
int n=5;
自动f=[=]{
return[=]{return n;};//创建一个有状态lambda并在一行中返回它
};

std::cout让我们说这是因为一个糟糕的实现:-)@CaptainObvlious好的-但是对于有状态的lambda,强制转换到函数指针是明确不允许的,对吗?[不确定“not”是如何进入我之前的评论的-抱歉;)]根据5.1.2/6,如果没有捕获,则需要进行转换。不过,该标准并未明确禁止将转换包含在有状态lambda中。我的理解是,因为它未指定,所以实现可以自由包含转换,即使是有状态lambda。有趣的是……但它可能只应执行以下操作:如果有必要的话,我会进行转换。标准是否解决了这一方面?(是否有我可以自己阅读标准的地方?我在互联网上找不到它。)有关信息,请参阅Visual Studio网站上错误报告的链接:“因此,在本例中,返回类型为
void
。”-这与编译器所说的不一致。编译器所说的返回类型是
int(\uu cdecl*)(void)
。此外,它还说它无法执行从
auto r=…;
行上的lambda类型到
f
的返回类型的转换,即
int(\uu cdecl*)(void)
。如果我错了,请纠正我,因为我有点困惑。@TimothyShields:GCC将代码接受为C++11是错误的(但对于C++14 CD来说是正确的)。Visual Studio不接受该代码是正确的,但原因是错误的:它不应该尝试将有状态lambda转换为函数指针。你能谈谈你对我最近这个相关问题的看法吗?我认为根据你的见解,我在那里得到的答案可能不正确。@TimothyShields:关于另一个问题,我很抱歉这是我无法补充的。我还用GCC 4.7.2尝试了你的代码,它编译得很好。这似乎确实是一个VS错误。我现在没有VS2012,但我用VS2010尝试了,我得到了一个类似的错误。VS2012和VS2010之间唯一的区别是前者说
t=void(u cdecl*)(void)
而后者说的是
T=int
。那么说“在C++11中,不能定义返回有状态lambda的lambda”是否正确?
   { attribute-specifier-seq[opt] return expression ; }
#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;
}