在 C++11 中用“auto”推导出 lambda 的类型是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7951377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the type of lambda when deduced with "auto" in C++11?
提问by iammilind
I had a perception that, type of a lambda is a function pointer. When I performed following test, I found it to be wrong (demo).
我有一种看法,即 lambda 的类型是一个函数指针。当我执行以下测试时,我发现它是错误的(演示)。
#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
assert(typeid(pFptr) == typeid(pAuto)); // assertion fails !
}
Is above code missing any point ? If not then, what is the typeof
a lambda expression when deduced with auto
keyword ?
上面的代码是否遗漏了任何一点?如果不是,那么typeof
用auto
关键字推导时的 lambda 表达式是什么?
回答by jalf
The type of a lambda expression is unspecified.
未指定 lambda 表达式的类型。
But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor. Anything inside the []
are turned into constructor parameters and members of the functor object, and the parameters inside ()
are turned into parameters for the functor's operator()
.
但它们通常只是函子的语法糖。一个 lambda 被直接翻译成一个函子。里面的任何东西[]
都变成构造函数参数和函子对象的成员,里面的参数()
变成函子的参数operator()
。
A lambda which captures no variables (nothing inside the []
's) can be convertedinto a function pointer (MSVC2010 doesn't support this, if that's your compiler, but this conversion is part of the standard).
不捕获任何变量([]
's 中没有任何内容)的 lambda可以转换为函数指针(MSVC2010 不支持此功能,如果这是您的编译器,但此转换是标准的一部分)。
But the actual type of the lambda isn't a function pointer. It's some unspecified functor type.
但是 lambda 的实际类型不是函数指针。这是一些未指定的函子类型。
回答by avakar
It is a unique unnamed structure that overloads the function call operator. Every instance of a lambda introduces a new type.
它是一个独特的未命名结构,它重载了函数调用运算符。lambda 的每个实例都引入了一种新类型。
In the special case of a non-capturing lambda, the structure in addition has an implicit conversion to a function pointer.
在非捕获 lambda 的特殊情况下,该结构还具有到函数指针的隐式转换。
回答by Lightness Races in Orbit
[C++11: 5.1.2/3]:
The type of the lambda-expression(which is also the type of the closure object) is a unique, unnamed non-union class type— called the closure type— whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [..]
[C++11: 5.1.2/3]:
的类型的λ-表达(这也是封闭的对象的类型)是一个独特的,无名不愈合类类型-称为闭合类型-其特性如下所述。这个类类型不是聚合(8.5.1)。闭包类型在包含相应lambda-expression的最小块作用域、类作用域或命名空间作用域中声明。[..]
The clause goes on to list varying properties of this type. Here are some highlights:
该子句继续列出这种类型的不同属性。以下是一些亮点:
[C++11: 5.1.2/5]:
The closure type for a lambda-expressionhas a publicinline
function call operator (13.5.4) whose parameters and return type are described by the lambda-expression's parameter-declaration-clauseand trailing-return-typerespectively. [..]
[C++11: 5.1.2/6]:
The closure type for a lambda-expressionwith no lambda-capturehas a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type's function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type's function call operator.
[C++11: 5.1.2/5]:
lambda 表达式的闭包类型有一个公共inline
函数调用运算符 (13.5.4),其参数和返回类型分别由lambda-expression的参数声明子句和尾随返回类型描述。[..]
[C++11: 5.1.2/6]:
没有lambda 捕获的lambda 表达式的闭包类型具有公共非虚拟非显式 const 转换函数,指向与闭包类型的函数调用运算符具有相同参数和返回类型的函数的指针。此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果。
The consequence of this final passage is that, if you used a conversion, you would be able to assign LAMBDA
to pFptr
.
最后一段的结果是,如果您使用转换,您将能够分配LAMBDA
给pFptr
.
回答by B?ови?
#include <iostream>
#include <typeinfo>
#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
std::cout<<typeid( *pAuto ).name() << std::endl;
std::cout<<typeid( *pFptr ).name() << std::endl;
std::cout<<typeid( pAuto ).name() << std::endl;
std::cout<<typeid( pFptr ).name() << std::endl;
}
The function types are indeed same, but the lambda introduces new type (like a functor).
函数类型确实相同,但 lambda 引入了新类型(如函子)。
回答by Syed Raihan
It should also note that lambda is convertible to function pointer. However typeid<> returns a non-trvial object which should differ from lambda to generic function pointer. So the test for typeid<> is not a valid assumption. In general C++11 do not want us to worry about type specification, all that matter if a given type is convertible to a target type.
还应该注意的是,lambda 可以转换为函数指针。然而 typeid<> 返回一个非平凡的对象,它应该不同于 lambda 到通用函数指针。所以 typeid<> 的测试不是一个有效的假设。一般来说,C++11 不希望我们担心类型规范,如果给定的类型可以转换为目标类型,这一切都很重要。
回答by Gabriel
A practical solution from How can I store a boost::bind object as a class member?, try boost::function<void(int)>
or std::function<void(int)>
.
如何将 boost::bind 对象存储为类成员的实用解决方案?,尝试boost::function<void(int)>
或std::function<void(int)>
。