lambda调用另一个外部lambda

lambda calling another external lambda

本文关键字:lambda 外部 调用 另一个      更新时间:2023-10-16

我可以很容易地做到这一点:

auto f = []()->int { return 4; };
auto g = [f]()->int { return f(); });
int i = g();

然而,我不能这样做:

int (*f)() = []()->int { return 4; };
int (*g)() = [f]()->int { return f(); });
int i = g();

为什么我在微软风投收到这样的信息?

error C2440: 'initializing' : cannot convert from 'ClassName::functionName::< lambda_b2eebcdf2b88a20d8b40b0a03c412089>' to 'int (__cdecl *)(void)'

这发生在线路上:

int (*g)() = [f]()->int { return f(); });

如何正确地做到这一点?

int (*f)() = []()->int { return 4; };

仍然可以,因为具有空捕获列表的lambda隐式转换为匹配的函数指针。

然而,这一(关键(条件在第二行中没有得到满足:

int (*g)() = [f]()->int { return f(); });
              ^

因此转换失败。

如果您想存储一个捕获某些内容的lambda,您要么需要一个std::function,要么像以前那样用auto推导类型;任何适合你的用例。函数指针根本无法做到这一点(在C++11中,关于未来,请参阅Yakk的答案(。

好吧,您可以等待C++17。

template<auto F>
struct function_ptr;
template<class R, class...Args, R(*F)(Args...)>
struct function_ptr<F> {
  using signature = R(Args...);
  constexpr R operator()(Args...args)const {
    return F(std::forward<Args>(args)...);
  }
  constexpr operator signature*() const { return F; }
  constexpr signature* operator+() const { return F; }
};

现在:

constexpr auto f_ = []()->int { return 4; };
function_ptr<+f_> f;

生成类似CCD_ 3的函数指针。

template<class T>struct tag_t {};
template<class F, class...Fs, class R, class...Args>
constexpr auto chain_functions(tag_t<R(Args...)>) {
  constexpr r = [](Args...args)->R{
    return F{}( Fs{}..., std::forward<Args>(args)... );
  };
  return function_ptr<+r>{};
}

让我们来链接函数指针。

constexpr auto f_ = []()->int { return 4; };
function_ptr<+f_> f0;
constexpr auto g_ = [](int(*f)())->int { return f(); });
function_ptr<+g_> g_raw;
auto g0 = chain_functions< function_ptr<+g_>, function_ptr<+f_> >( tag_t<int()>{} );

现在CCD_ 4是CCD_。

int(*g)() = g0;

应该有望编译并工作。(没有经过测试,我没有足够的C++17编译器(。

还是有点迟钝,绝对没有经过测试。基本上,function_ptr旨在创建一个带有编译时函数指针的类型。C++17为我们提供了constexpr lambda,包括在constexpr上下文中从它们中获取函数指针的能力。

然后,我们可以组合这些函数指针类型来生成新的函数指针类型。