【问题标题】:How to return a lambda function?如何返回一个 lambda 函数?
【发布时间】:2014-06-26 13:22:36
【问题描述】:

例如,我可以将 lambda 函数定义为

auto f = [](double value) {double ratio = 100; return value * ratio;}

现在我想生成一个带有比率参数的函数并返回 lambda 函数,如

auto makeLambda(double ratio) { return [=](double value) {return value * ratio;}; }

怎么做?

【问题讨论】:

  • 你有什么问题?
  • @chris: 需要 C++14 来推断函数返回类型。

标签: c++ c++11 lambda


【解决方案1】:

使用 C++14 函数返回类型推导,应该可以。

在 C++11 中,您可以定义另一个 lambda(它可以推断返回类型),而不是一个函数(它不能):

auto makeLambda = [](double ratio) {
    return [=](double value) {return value * ratio;};
};

如 cmets 中所述,如果您特别想要一个函数,可以进一步包装:

auto makeLambdaFn(double ratio) -> decltype(makeLambda(ratio)) {
    return makeLambda(ratio);
}

【讨论】:

  • 您忘记进行内部 lambda 捕获。
  • 该示例在 idone 中有效,但在 vc2013 中失败。 VC2013 还不够 c++11。
  • 如果您想要一个函数而不是 lambda,请再次将 lambda 包装在一个函数中:auto func(double x)->decltype(makeLambda(x)){return makeLambda(x);}
【解决方案2】:

@disclaimer:这个答案只是为@Slava 的答案添加了额外的参数(但对于评论来说太长了)。

你可能不应该返回一个 lambda,而是一个函数指针或一个 std::function。

除了效率问题(见下文),API 的声明应该告诉您如何使用它。 lambda 是一个临时函数 - 旨在让您在哪里使用它(在本地上下文中)有意义。

如果你这样写:

std::function<double( double )> makeFunction(double ratio);

您的代码将更加灵活(不依赖于 C++14)、更好的定义(您可以查看签名并知道它的作用)和面向未来(很容易理解代码背后的意图) API,便于以后扩展而不会搞砸客户端代码)。

如果你这样写:

auto makeFunction(double ratio);

你必须内联定义它(我猜)。

对于类似于 MikeSeymour 的答案的实现,您需要添加一个额外的 lambda,以避免编译器的限制。读取带有返回 lambda 的 lambda 的实现只是为了弄清楚 API 返回的内容,这是一个很大的禁忌。

首先,因为它是不明显和晦涩的。

其次,它将强加于客户端代码,即需要注释/解释性说明才能理解的 API,或者强制客户端阅读其实现以了解如何使用它。

如果您不能保证这是一次性代码,您将:

  • 增加代码的WTF/SLOC比率(代码目的不明确,如果你需要阅读实现来弄清楚它返回什么)

  • 有一些不明显的东西,你必须为整个项目维护。这被称为 cruft,这就是让糟糕的遗留代码成为糟糕的遗留代码的原因。

如果你需要返回一个仿函数,你最好返回一个std::function;返回类型实际上是在尖叫“返回一个函子”。

如果这对您的需求来说效率太低,您可以稍后对其进行优化/具​​体化) - 例如,通过返回一个 struct X { double operator()(double); } 实例。

关于能够保证这不是生产代码的说明:

我见过很多情况:

  • 我正在查看可怕的三年前代码,人们告诉我最初这是原型,但我们向客户展示了应用程序,他们要求它“原样”,并且现在客户依赖它,但我们没有时间预算来清理它

  • 我将丑陋的原型代码发送给其他人(如“我们可以按照此算法做一些事情”),并在稍后将其作为源代码控制中的解决方案提交。

  • 人们在 hack 上写了 hack,因为代码已经很 hacky,再 hack 也没关系(实际上这是一个很常见的借口)。

【讨论】:

    【解决方案3】:

    您可以返回std::function&lt;double( double )&gt;。调用它可能会产生额外的函数调用成本,这在大多数情况下是微不足道的。

    【讨论】:

    • 如果您还描述了其中的含义(主要是为了提高效率),这将是一个很好的答案。
    • @Angew 你有关于这方面的信息吗?我需要复习我的 C++11 :)
    • @JoachimIsaksson 最大的是std::function 使用了一种称为“类型擦除”的技术,这会在每次调用时产生一个间接调用(通常作为虚函数实现)。
    • @JoachimIsaksson 简单说什么。
    • +1;我添加了一个基本上支持这一点的答案(评论太长了)。
    猜你喜欢
    • 2019-04-10
    • 1970-01-01
    • 2015-08-27
    • 2017-07-25
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    相关资源
    最近更新 更多