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)
- 我记得这只适用于无状态lambda(那些具有空捕获子句的lambda),而内部lambda
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;
}