在C ++ 11中用“auto”推导出lambda的类型是什么?

时间:2011-10-31 08:36:51

标签: c++ lambda c++11 typeof auto

我有一种感觉,lambda的类型是一个函数指针。当我执行以下测试时,我发现它是错误的(demo)。

#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 !
}

以上代码是否缺少任何一点?如果没有,那么使用typeof关键字推导出auto lambda表达式是什么?

7 个答案:

答案 0 :(得分:120)

未指定lambda表达式的类型。

但它们通常仅仅是算子的语法糖。 lambda直接转换为仿函数。 []内的任何内容都会转换为构造函数参数和仿函数对象的成员,并且()中的参数将转换为仿函数operator()的参数。

一个没有变量的lambda([]内没有任何东西)可以转换成到一个函数指针(MSVC2010不支持这个,如果那是你的编译器,但这个转换是标准的一部分。)

但是lambda的实际类型不是函数指针。这是一些未指定的仿函数类型。

答案 1 :(得分:96)

它是一个唯一的未命名结构,它使函数调用运算符重载。 lambda的每个实例都引入了一个新类型。

在非捕获lambda的特殊情况下,该结构还有一个隐式转换为函数指针。

答案 2 :(得分:22)

  

[C++11: 5.1.2/3]: lambda-expression 的类型(也是闭包对象的类型)是一个唯一的,未命名的非union类类型 - 称为闭包类型 - 其属性如下所述。此类类型不是聚合(8.5.1)。闭包类型在包含相应 lambda-expression 的最小块作用域,类作用域或命名空间作用域中声明。 [..]

该子句继续列出此类型的不同属性。以下是一些亮点:

  

[C++11: 5.1.2/5]: lambda-expression 的闭包类型有一个公共inline函数调用运算符(13.5.4),其参数和返回类型由 lambda-expression 分别是 parameter-declaration-clause trailing-return-type [..]

     

[C++11: 5.1.2/6]:没有 lambda-capture lambda-expression 的闭包类型具有指向的指针的公共非虚拟非显式const转换函数函数具有与闭包类型的函数调用操作符相同的参数和返回类型。此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用操作符具有相同的效果。

最后一段话的结果是,如果您使用了转换,则可以将LAMBDA分配给pFptr

答案 3 :(得分:2)

#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;
}

函数类型确实相同,但lambda引入了新类型(如仿函数)。

答案 4 :(得分:1)

还应该注意lambda可以转换为函数指针。然而,typeid&lt;&gt;返回一个非平凡的对象,该对象应该与lambda和泛型函数指针不同。所以对于typeid&lt;&gt;的测试不是一个有效的假设。一般来说,C ++ 11不希望我们担心类型规范,如果给定类型可以转换为目标类型,那么重要。

答案 5 :(得分:1)

这可能有效:

<Button>
    h1 {
        font-size:20px;
      }
    h2{
        font-size:18px;
      }
    p {
        font-size: 16px;
      }
    exmp{
        font-size:16px;
        color:#000077;
        /*font-style: oblique;*/
        font-family: Lucida Console;
      }

答案 6 :(得分:0)

来自How can I store a boost::bind object as a class member?的实用解决方案,尝试boost::function<void(int)>std::function<void(int)>