【问题标题】:C++ lambda size [closed]C ++ lambda大小[关闭]
【发布时间】:2017-10-03 11:33:47
【问题描述】:

这是一个不能调用任何 lambda 的 lambda 类的示例。它旨在用作仿函数。

template<class T>
struct lambda_class {
 T lambda;
 void operator()(){ lambda();}
};

这个类是否有任何尺寸保证。我需要将它存储在联合中,但如果没有特定的模板参数,我不能将它放在联合中。为此,我需要知道 lambda 的最大大小是多少。它何时是特定于编译器的并不重要。

编辑 1: 是的,我的目的是了解 std::function 是如何在内部实现的。出于这个原因,我选择 EASTL 进行理解,因为与 gnu libstdc++ 相比,它的可读性非常好。

以下链接包含似乎仅使用placement new 的函数实现代码: https://github.com/electronicarts/EASTL/blob/master/include/EASTL/internal/function.h

我不明白为什么它适合存储类型?第 131 和 141 行包含函子和分配器的结构定义。当 lambda 与多个捕获的变量绑定时会发生什么?

【问题讨论】:

  • "which cann call any lambda" 你确定吗?这不需要一些可变参数和转发吗?
  • 由于 lambda 可以捕获,因此它的大小没有限制,除非机器可以处理。
  • 那不是类,是类模板。您不能在任何地方创建它的实例。您似乎正在尝试重新创建 std::function&lt;void()&gt;。
  • 不管 lambda 的大小如何,关于“将其存储在联合中”的主题:不要。除非您准备编写一大堆丑陋的代码,以正确实现存储在联合中的对象的构造函数和析构函数语义。这是一个你不能忽视的强制性要求,否则你会得到一些很好的未定义行为,作为你的奖励。使用std::variant 而不是联合,它将为您完成所有繁重的工作。

标签: c++ c++11 templates lambda


【解决方案1】:

您似乎想要std::function&lt;void()&gt;。

std::function&lt;void()&gt; 可以存储任何可以复制和销毁的可调用对象(可以使用 0 个参数调用)。它要么将其存储在内部缓冲区中(大到足以存储函数指针),要么存储在堆中(如果它太大)。

它通过一种称为类型擦除的机制来做到这一点。

它不是 lambda,但它可以存储 lambda。

在联合中存储非 POD C++ 类有点痛苦。如果您有 支持,请考虑使用 boost::variant 或 std::variant。

在没有std::function 和variant 的情况下解决这个问题,如果您想知道如何将模板(而不是模板实例)存储为数据,我会觉得很难,并且超出您的技能水平几步.

【讨论】:

  • 我的目的是避免使用堆。目前,这似乎很难。使用堆内存会很容易。
  • @Gustavo 问以下问题:“我想要一个不使用堆的std::function&lt;void()&gt;。我可以接受它不适用于所有 lambda,但理想情况下我希望它在如果我使用过大的 lambda,则构建时间。” ——或者,更确切地说,试着写下来,当你遇到问题时再回来提出更多问题。了解类型擦除、std 函数、std::aligned storage、placement new 等。
  • 好的,那么最后一个问题:是否可以不使用动态内存分配?在我看来,不是不知道仿函数对象的最大存储大小。使用堆时,我可以使用基类和模板化子类。
  • @Gustavo 是的,如果您愿意限制存储的 lambda 的最大大小/对齐方式。这可以在编译时检查,因此如果您尝试存储过大的 lambda,您会收到构建错误。您仍然可以使用虚拟调度解决方案进行类型擦除,但在使用 SBO 存储对象时,我更喜欢使用手动 vtable 解决方案进行类型擦除。
猜你喜欢
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 2019-12-20
  • 1970-01-01
  • 2012-09-24
  • 2018-05-18
相关资源
最近更新 更多