是否有可能提取lambda的捕获列表?

时间:2016-03-16 02:30:06

标签: c++ c++11 lambda

this链接我理解为了传递lambda,我们需要将该方法作为参数传递并将其存储在std :: function类型中。在这种情况下,是否可以从lambda的捕获列表中提取参数?

例如

struct foo
{
    std::vector<int> t = {1,2,3};
};

void funct(std::function<void()> func)
{
    func(); //This works fine . Can I extract the object foo from this lambda ?
}

int main()
{
   foo a;
   a.t.push_back(45);
   funct( [a](){ std::cout << "New value is " << a.t[3] ; } );
}

2 个答案:

答案 0 :(得分:2)

为了访问存储在std::function对象中的对象,您必须use the std::function::target<T> template function。在这种情况下,T是您传递给function构造函数的对象的实际类型。

事实证明,lambda的类型是无法解决的。也就是说,标准要求,无论编译器分配什么类型名称,它都是无法在键盘上输入的类型名称。如果您还没有(直接或通过类型的类型的类型扣除),那么您无法做到这一点。

现在,您可以这样做:

template<typename T>
void funct(T func)
{
    std::function<void()> stdfunc(func);

    T *ptr_func = stdfunc.target<T>();
}

当然,这是多余的,因为你已经有了lambda函数的类型。

但是,即使使用上面的代码,也无法访问lambda的捕获变量。为什么?因为标准并没有说你可以。

关于lambda闭包你可以做的事情的简短列表:

  • 复制/移动构造它们,假设捕获的类型是复制/可移动的。
  • 摧毁他们。
  • 使用operator()调用它们。
  • 将它们转换为函数指针,但前提是lambda是无捕获的(并且是非泛型的)。

不需要实现来允许您访问lambda的成员变量。因此,没有标准的方法可以这样做。即使实现使它们公开并按照它们在代码中命名的方式命名(两者都不是必需的),C ++标准也不能保证每个实现都必须这样做。

答案 1 :(得分:0)

我认为你不能。因为lambdas等同于其operator()已被重载的类。捕获的参数实际上是私有数据成员。在此示例中,您的lambda等效于:

class _lambda {
  public:
    void operator()() const {
        std::cout << "New value is " << a.t[3];
    }
  private:
    foo a;
}

我认为你无法访问友谊未婚的私人会员。