使用函数在C ++中嵌套无捕获的lambdas?

时间:2018-03-10 05:43:58

标签: c++ lambda constexpr stateless

问题

在C ++中传递它们时是否可以嵌套无捕获的lambda?

从我能收集到的情况看来似乎并非如此;相反,你似乎必须制作一个模板类,并定义静态函数,然后传递它们。

背景

与此帖相关,适用于pybind11Possible to have logical operations (e.g. `ndarray.__eq__`) not return `bool` in NumPy?

基本上,我想看看我是否可以避免宏并且仍然提供无状态函数(没有任何类型擦除的void* data恶作剧)与Numpy UFunc API一起使用。

我的目标是无状态,因为看起来API有一些函数可以有void* data,我可以使用它来传递另一个函数指针(或删除带有捕获的lambda),但有些他们似乎没有。

盲目黑客

这是我的黑客行为:

// Goal: Wrap a function of type `Func` without capture.
typedef void (*Func)();


// NOPE: `b` ain't stateless.
Func wrap(Func a) {
  return [a]() { a(); };
}
int main() {
  Func a = []() { cout << "A1\n"; };
  wrap(a)();
}


// KINDA: Compiles, but `a` wasn't a parameter :(
// - Could use arrays a constexpr indices to fake it :( * 2
int main() {
  static const Func a = []() { cout << "A1\n"; };
  Func b = []() { a(); };
  b();
}

// YUP-ish: Works, cannot deal with lambdas :(
template <Func a>
Func wrap() {
  return []() { a(); };
}
// - Cannot be in a class in function scope :(
void a2() { cout << "A2\n"; }
int main() {
  Func b = wrap<tmp::a2>();
  b();
}

// NOPE: Lambda doesn't have default constructor (but what else would it do???)
int main() {
  auto a = []() { cout << "A3\n"; };
  using A = decltype(a);
  Func b = []() { A a{}; a(); };
  b();
}

我看到constexpr lambdas有一些新内容,但这似乎更多的是返回值是constexpr,而不是lambda本身的定义(所以它可以作为模板参数或其他任何方式传递。

2 个答案:

答案 0 :(得分:3)

您可以将lambda复制到静态变量中:

template<typename F>
auto wrap(F a) {
    static auto F b = std::move(a);
    return []() { b(); };
}

每个lambda都有不同的类型,因此对于每个lambda,都会创建一个新的静态变量,因为该函数是模板化的。

请注意,仅当传递的callable具有不同的类型时才有效。如果你只使用无状态函数对象,你就不会有任何问题。

作为一名安全警卫,您还可以确保只发送无人值守的lambda:

template<typename F, std::void_t<
    decltype(+std::declval<F>()),
    decltype(&F::operator())
>* = nullptr>
auto wrap(F a) {
    static auto F b = std::move(a);
    return []() { b(); };
}

sfinae表达式查找带有catpureless lambda的一元operator+,并且它还会查找lambda的operator()成员的存在。

答案 1 :(得分:0)

Lambda函数不是指向函数的指针,它是一个对象。虽然它可以转换为指针,但它不能作为指针返回,就像任何本地对象都不能通过指针返回一样,应该返回一个副本。正确的代码如下。

#include <functional>
using namespace std;

typedef void (*Func)();

std::function<void()> wrap(Func a) {
  return [a]() { a(); };
}

最后一个怎么样。你声明了一个&#34;功能&#34; a此处A a;但未分配功能&#34; body&#34;。试试这个

int main() {
  auto a = []() { cout << "A3\n"; };
  using A = decltype(a);
  auto b = [a]() { A c(a); c(); };
  b();
}