【问题标题】:How to get state reference from lambda with capture clause?如何使用捕获子句从 lambda 获取状态引用?
【发布时间】:2013-04-02 10:57:02
【问题描述】:

Lambda 可以使用 [=] 语法从创建它们的上下文中捕获成员。我假设必须有一个状态引用存储在 lambda 中,类似于 this 指针。

class Class
{
public:
    void Function()
    {
        /*
         * pass this lambda expression as parameter to another
         * function and from there recover the this pointer which
         * would be of the type Class* for further usage.
         */

        [=](int)->int { /* do something with this->Member */ }
    }
private:
    int Member;
};

有没有办法从 lambda 表达式中获取引用指针?

【问题讨论】:

  • 可以捕获this:[=, this](int)->int { }
  • @jrok: this 已被捕获。问题是,捕获的值能否从 lambda 对象中恢复?
  • 读了第二遍,明白了你的意思,确实是个有趣的问题。但我想不会,因为我猜,从 Membercaptured_this_pointer->Member 在 lambda 函数体内的映射是在幕后。

标签: c++ lambda closures this std


【解决方案1】:

不,您无法从 lambda 对象中恢复捕获的值或引用。

lambda 类型没有公共数据成员,唯一的公共成员函数是函数调用运算符、构造函数、析构函数、赋值运算符和转换为函数指针的运算符(如果它不捕获任何内容)。这些都不能用于提取捕获的实体。

【讨论】:

  • @danijar:不幸的是,没有;无法扩展 lambda 类型。您可以获得的最接近的方法是定义一个具有函数调用运算符、构造函数和成员变量以显式捕获事物的类,以及您需要的任何扩展接口。您可以使用类声明语法 MyLambda(this) 而不是 lambda 语法来创建它。
  • 谢谢。你知道最简单的方法是将 lambda 作为参数传递给函数并在那里访问函数指针和状态引用吗?当然我必须传递额外的参数。顺便问一下,lambda 类型的实际名称是什么?我可以将其存储为 lambda 类型而不是 std::function 吗?
  • @danijar:lambda 类型没有名称。但是,您可以将它传递给一个函数,而无需将其转换为 std::function,方法是将函数设为模板:template <typename Lambda> void f(Lambda)
  • @danijar:如果实体是按值捕获的,那么就没有办法访问它们;如果需要,您必须定义自己的函数类而不是 lambda。如果它们是通过引用捕获的,那么您可以将自己的引用传递给相同的对象。
  • 所以我必须将我自己的引用作为参数传递给不再有捕获子句的 lambda,对吗?有没有办法std::bind对lambda参数的引用,这样我最终得到一个没有引用参数的函数指针?
【解决方案2】:

补充 Mike 的回答:您实际上可以恢复存储在 lambda 中的任何信息...通过在调用时返回(或将其存储在 out-parameters 中)。甚至可以在 lambda 中捕获对变量的引用,请记住,该引用仅在 lambda 存在时才可用。

当然,这可能需要更改 lambda 的签名。

[=](int i) -> std::pair<int, X*> {
    return std::make_pair(i, this);
}

【讨论】:

  • 听起来很有趣,你能举个例子吗?
  • 我知道,但我无法执行 lambda 来获取 this 指针。无论如何,谢谢。
  • @danijar 如果您可以重写 lambda 本身,您可以“巧妙地”使整个主体成为某种 if 语句,以返回捕获的元素或执行“真实”函数lambda 代表....但几乎可以肯定这太聪明了,不值得进行编程实践。
【解决方案3】:

试试 [this] 而不是 [=]。

我建议供进一步参考 http://www.cprogramming.com/c++11/c++11-lambda-closures.html

目前我大部分时间都倾向于使用 [&] 作为捕获。它很便宜,而且通常 lambda 表达式足够短,因此很安全。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2016-02-08
    • 2012-08-21
    • 1970-01-01
    相关资源
    最近更新 更多