【问题标题】:lambda with conversion function to pointer to function with c++ linkage具有转换函数的 lambda 到具有 c ++ 链接的函数的指针
【发布时间】:2019-03-29 07:52:57
【问题描述】:

C++ 标准有如下声明:

非泛型 lambda 表达式的闭包类型,没有 满足约束(如果有)的 lambda-capture 具有 将函数转换为指向具有 C++ 语言链接的函数的指针 (10.5) 具有与闭包相同的参数和返回类型 类型的函数调用运算符。

为了更好地理解该语句,我使用cppinsights 来查看clang 编译器对以下函数的说明。

#include <iostream>

using test = void (*)(int);

int main()
{
    test t = [](int arg) { std::cout << arg << std::endl; };
}

cppinsights 将函数翻译为:

#include <iostream>

using test = void (*)(int);

int main()
{

  class __lambda_7_11
  {
    public: inline void operator()(int arg) const
    {
      std::cout.operator<<(arg).operator<<(std::endl);
    }

    public: using retType_7_11 = void (*)(int);
    inline operator retType_7_11 () const
    {
      return __invoke;
    }

    private: static inline void __invoke(int arg)
    {
      std::cout.operator<<(arg).operator<<(std::endl);
    }


  } __lambda_7_11{};

  using FuncPtr_7 = test;
  FuncPtr_7 t = static_cast<void (*)(int)>(__lambda_7_11.operator __lambda_7_11::retType_7_11());
}

像往常一样,编译器生成一个匿名类,其中 operator() 重载,以及标准规定的“将函数转换为指向函数的指针”。

我不明白为什么会生成“静态__invoke”函数,而“转换函数”在内部调用“__invoke”(直接作为函数指针)而没有“__invoke”预期的任何参数?

【问题讨论】:

  • 提示:查看操作符的返回类型。该函数未被调用。
  • @Rakete1111 你的意思是“__invoke”吗?它是一个函数指针。
  • 它是一个函数,返回类型是一个函数指针。 __invoke 不在任何地方调用。

标签: c++ c++11 lambda c++17


【解决方案1】:

我不明白的是为什么会生成static __invoke 函数并且“转换函数”在内部调用__invoke(直接作为函数指针)而没有__invoke 所期望的任何参数?

转换函数不会“内部调用”__invoke,它只是返回 __invoke,即指向static 成员函数的指针。请记住,static 和非static 成员函数之间的区别在于前者没有绑定到该类的特定实例,因此可以将其视为普通函数指针,而不是指向成员的指针。看看下面的例子:

struct Test {
   void f();
   static void g();
};

void (Test::*f)() = &Test::f; // pointer to instance-specific member fct.
void (*g)() = &Test::g; // ordinary function pointer
void (*h)() = Test::g; // no ampersand, this is implicitly a function pointer

后者是您想要的转换结果,而 cppinsights 向您展示的只是一种实现这种转换的技术:由于 lambda 表达式有一个空闭包,编译器生成的函数对象没有状态,没有状态的对象的成员函数可以是static 可以绑定到普通函数指针的成员函数。

【讨论】:

  • 这是有道理的。另一个问题是为什么函数指针使用“typedef”,为什么不能在函数定义中直接提及?
  • @Almx1:因为 cppinsights 的作者发现它更具可读性?我什至不知道你是否可以在转换运算符中使用()。
【解决方案2】:

Cppinsights 的作用是正确的。它返回调用函数的函数指针iso。

如果按以下方式编写会更易读:

inline operator retType_7_11 () const
{
  return &__invoke;
}

但是,在这种情况下,& 不是必需的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 2012-06-17
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    相关资源
    最近更新 更多