C ++中的Lambda闭包等效项

问题描述 投票:0回答:1

[我正在观看Kevlin Henney的名为Lambda? You Keep Using that Letter的视频,他在其中指出闭包和对象在本质上是等效的:

他然后通过this javascript code证明了自己的观点,该观点将堆栈实现为闭包:

const newStack = () => {
    const items = []
    return {
        depth: () => items.lengh,
        top: () => items[0],
        push: newTop => { items.unshift(newTop) },
        pop: () => { items.shift() },
    }
}

闭包与类相比的优势在于,它的状态实际上是隐藏的,而私有成员比“隐藏”更“不可访问”。

我试图在C ++中做等效的事情。但是,似乎很难用C ++表示出来。

我的当前版本在那里,它有两个主要缺点:

  • 它确实可以编译,但是不起作用(内部shared_ptr在创建闭包后立即释放)

  • 有点冗长:将depth,top,push和pop重复3次。

auto newStack = []() {
  auto items = std::make_shared<std::stack<int>>();

  auto depth = [&items]() { return items->size();};
  auto top = [&items]() { return items->top(); };
  auto push = [&items](int newTop) {  items->push(newTop); };
  auto pop = [&items]() { items->pop(); };

  struct R {
    decltype(depth) depth;
    decltype(top) top;
    decltype(push) push;
    decltype(pop) pop;
  };
  return R{ depth, top, push, pop};
};

godbolt version here

在C ++中有可行的方法吗?

c++ lambda closures
1个回答
3
投票

是的,当然,在C ++中有更好的方法:不要使用lambda。

lambda表达式定义一个类。闭包是该类的一个实例-一个对象。我们不需要与其他语言进行比较就可以告诉我们-这正是C ++中lambda和闭包的定义方式。 §[expr.prim.lambda.closure]:

lambda表达式的类型(也是闭包对象的类型)是一种唯一的,未命名的非工会类类型,称为闭包类型,其属性在下面进行描述。

但是(至少这是重要的一点)至少在C ++中,lambda表达式定义了一个very受限公共接口的类。具体来说,它提供operator()的重载,并且如果不捕获任何内容,则转换为指向函数的指针。如果确实捕获了某些内容,它还将定义一个构造函数来进行捕获。当然,如果它捕获了事物,它会定义成员变量以保存捕获的任何事物。

但这就是它真正定义的全部。这并不是说它可以更好地隐藏它可能包含的其他内容。因为它确实不包含任何其他内容。

在您的情况下,您试图定义一个类型,该类型具有四个单独的成员函数,这些成员函数均在它们共享的某些状态下运行。正如您所展示的,可以将状态外部化,这样您就有了几乎等同于一些仅包含数据的C代码(或该顺序的某些东西)和一些对该数据进行操作的函数。是的,您可以将它们组合到一个结构中,以至少对具有成员函数的类进行一些模仿。

但是您正在与系统作斗争(可以这么说),以便在C ++中做到这一点。 Lambda /闭包(如C ++中定义的)无意让您定义具有多个单独入口点的事物,每个入口点对共享数据执行单独的操作。正如塞缪尔·约翰逊(Samuel Johnson)的老话所说:“ [它就像一条狗在后腿上行走。虽然做得不好,但是您发现它完全可以感到惊讶。”

© www.soinside.com 2019 - 2024. All rights reserved.