如何返回lambda函数?

时间:2021-01-13 18:01:22

For example, I can define a lambda function as

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

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

Now I want to generate a function with the ratio an argument and return the lambda function like

现在我想生成一个比例为参数的函数并返回lambda函数

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

How to do it?

怎么做?

3 个解决方案

#1


21  

With C++14 function return type deduction, that should work.

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

In C++11, you could define another lambda (which can deduce the return type), rather than a function (which can't):

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

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

As noted in the comments, this could be further wrapped, if you particularly want a function:

如评论中所述,如果你特别需要一个函数,这可以进一步包装:

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

#2


12  

@disclaimer: this answer just adds extra arguments to @Slava's answer (but is too long for a comment).

@disclaimer:这个答案只是为@ Slava的答案添加了额外的论据(但是评论太长了)。

You probably should not return a lambda, but a function pointer or a std::function.

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

Efficiency concerns asside (see below), the declaration of an API should tell you how to use it. A lambda is a temporary function - something designed to make sense where you use it (in a local context).

效率问题有助于(见下文),API的声明应告诉您如何使用它。 lambda是一个临时函数 - 用于在使用它时(在本地环境中)有意义的东西。

If you write this:

如果你写这个:

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

Your code will be much more flexible (not depending on C++14), much better defined (you can look at the signature and know what it does) and future-proof (it is easy to understand the intent behind the API, which makes easy to extend later without screwing up client code).

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

If you write this:

如果你写这个:

auto makeFunction(double ratio);

You have to define it inline (I guess).

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

For an implementation similar to MikeSeymour's answer, you need to add an extra lambda, to avoid a limitation of the compiler. Reading an implementation with a lambda returning a lambda just to figure what the API returns, is a big no-no.

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

First, because it is non-obvious and obscure.

首先,因为它不明显而且模糊不清。

Second, it will impose on client code, an API that either needs a comment/explanatory note to make sense, or forces clients to read it's implementation to know how to use it.

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

If you cannot guarantee this is throw-away code, you will:

如果您不能保证这是丢弃代码,您将:

  • increase WTF/SLOC ratio of your code (code is not clear in purpose, if you need to read the implementation to figure out what it returns)

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

  • have something non-obvious, that you will have to maintain for the whole project. This is called cruft and is what makes sucky legacy code be sucky legacy code).

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

If you need to return a functor, you're better off returning a std::function; The return type practically screams "returning a functor".

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

If this is too inefficient for your needs, you can optimize/particularize it later) - for example, by returning a struct X { double operator()(double); } instance.

如果这对您的需求来说效率太低,您可以稍后优化/细化它 - 例如,通过返回struct X {double operator()(double);实例。

A note about being able to guarantee that this is not production code:

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

I've seen many cases where:

我见过很多案例:

  • I was looking at horrible three-year old code, where people told me originally this was the prototype, but we showed the app to the clients, they asked for it "as it is", and now clients depend on it, but we don't have the time budget to clean it up.

    我看着可怕的三年旧代码,人们告诉我原来这是原型,但是我们向客户展示了应用程序,他们“按原样”询问它,现在客户依赖它,但我们不知道没有时间预算来清理它。

  • I sent ugly prototype code to someone else (as in "we could do something that follows this algorithm") and saw it committed as a solution in source control later.

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

  • People wrote hacks over hacks because the code was already hacky and one more hack doesn't matter (that's a very common excuse actually).

    人们写黑客攻击黑客,因为代码已经很黑,而且还有一个黑客并不重要(这实际上是一个非常普遍的借口)。

#3


4  

You can return std::function<double( double )>. Calling it may have a cost of additional function call, which is insignificant in most cases.

您可以返回std :: function 。调用它可能需要额外的函数调用,这在大多数情况下是微不足道的。 (double)>

#1


21  

With C++14 function return type deduction, that should work.

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

In C++11, you could define another lambda (which can deduce the return type), rather than a function (which can't):

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

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

As noted in the comments, this could be further wrapped, if you particularly want a function:

如评论中所述,如果你特别需要一个函数,这可以进一步包装:

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

#2


12  

@disclaimer: this answer just adds extra arguments to @Slava's answer (but is too long for a comment).

@disclaimer:这个答案只是为@ Slava的答案添加了额外的论据(但是评论太长了)。

You probably should not return a lambda, but a function pointer or a std::function.

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

Efficiency concerns asside (see below), the declaration of an API should tell you how to use it. A lambda is a temporary function - something designed to make sense where you use it (in a local context).

效率问题有助于(见下文),API的声明应告诉您如何使用它。 lambda是一个临时函数 - 用于在使用它时(在本地环境中)有意义的东西。

If you write this:

如果你写这个:

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

Your code will be much more flexible (not depending on C++14), much better defined (you can look at the signature and know what it does) and future-proof (it is easy to understand the intent behind the API, which makes easy to extend later without screwing up client code).

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

If you write this:

如果你写这个:

auto makeFunction(double ratio);

You have to define it inline (I guess).

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

For an implementation similar to MikeSeymour's answer, you need to add an extra lambda, to avoid a limitation of the compiler. Reading an implementation with a lambda returning a lambda just to figure what the API returns, is a big no-no.

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

First, because it is non-obvious and obscure.

首先,因为它不明显而且模糊不清。

Second, it will impose on client code, an API that either needs a comment/explanatory note to make sense, or forces clients to read it's implementation to know how to use it.

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

If you cannot guarantee this is throw-away code, you will:

如果您不能保证这是丢弃代码,您将:

  • increase WTF/SLOC ratio of your code (code is not clear in purpose, if you need to read the implementation to figure out what it returns)

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

  • have something non-obvious, that you will have to maintain for the whole project. This is called cruft and is what makes sucky legacy code be sucky legacy code).

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

If you need to return a functor, you're better off returning a std::function; The return type practically screams "returning a functor".

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

If this is too inefficient for your needs, you can optimize/particularize it later) - for example, by returning a struct X { double operator()(double); } instance.

如果这对您的需求来说效率太低,您可以稍后优化/细化它 - 例如,通过返回struct X {double operator()(double);实例。

A note about being able to guarantee that this is not production code:

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

I've seen many cases where:

我见过很多案例:

  • I was looking at horrible three-year old code, where people told me originally this was the prototype, but we showed the app to the clients, they asked for it "as it is", and now clients depend on it, but we don't have the time budget to clean it up.

    我看着可怕的三年旧代码,人们告诉我原来这是原型,但是我们向客户展示了应用程序,他们“按原样”询问它,现在客户依赖它,但我们不知道没有时间预算来清理它。

  • I sent ugly prototype code to someone else (as in "we could do something that follows this algorithm") and saw it committed as a solution in source control later.

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

  • People wrote hacks over hacks because the code was already hacky and one more hack doesn't matter (that's a very common excuse actually).

    人们写黑客攻击黑客,因为代码已经很黑,而且还有一个黑客并不重要(这实际上是一个非常普遍的借口)。

#3


4  

You can return std::function<double( double )>. Calling it may have a cost of additional function call, which is insignificant in most cases.

您可以返回std :: function 。调用它可能需要额外的函数调用,这在大多数情况下是微不足道的。 (double)>