简体   繁体   English

在 C++17 中将 lambda 作为方法参数传递的最简单方法

[英]Simplest way to pass a lambda as a method parameter in C++17

Google is showing me lots of SO posts on passing lambdas as arguments, but they all seem to be C++0x/C++11 based (eg Use a lambda as a parameter for a C++ function ) and I understand this is an area that has improved in more recent C++ versions? Google is showing me lots of SO posts on passing lambdas as arguments, but they all seem to be C++0x/C++11 based (eg Use a lambda as a parameter for a C++ function ) and I understand this is an area在最近的 C++ 版本中有所改进?

I want to pass what is effectively a very simple delegate return MyGlobals.GetX() as a method variable - in my case MyGlobals is a global object.我想将一个非常简单的委托return MyGlobals.GetX()作为方法变量传递——在我的例子中, MyGlobals是一个全局 object。 ie in pseudocode即在伪代码

//stores and/or calls the lambda
myObject.SetXGetter({return MyGlobals.GetX()});

MyObject::SetXGetter(lambda?)
{
 this->mLambda = Lambda;
 cout << mLambda();
}

Older C++ versions made this quite messy having to use STL wrappers and temporary types, so in C++17 and above, how neatly can it be done... what would SetGetter look like and can it be called passing the lambda directly in? Older C++ versions made this quite messy having to use STL wrappers and temporary types, so in C++17 and above, how neatly can it be done... what would SetGetter look like and can it be called passing the lambda directly in?

(If there are different alternatives for even newer versions, please share) (如果更新版本有不同的替代方案,请分享)

A function that just wants to invoke a passed lambda or other functor during its own execution can be a function template, deducing the type of the functor:一个 function 在它自己的执行过程中只想调用一个传递的 lambda 或其他仿函数可以是一个 function 模板,推断仿函数的类型

template <typename F>
void use_it(F&& func) {
    do_something_with(func());
}

Here you want to store the functor to be invoked later, so we'll need a common type that can wrap around various sorts of functors.在这里,您想要存储稍后调用的函子,因此我们需要一个可以包装各种函子的通用类型。 This is what std::function is for.这就是std::function的用途。 Assuming a return type of int :假设返回类型为int

#include <functional>

class MyObject {
// ...
private:
    std::function<int()> mLambda;
};
void MyObject::SetXGetter(std::function<int()> func) {
    mLambda = std::move(func);
}

Your call is missing the initial [ captures ] which is required for a lambda expression, even if nothing is captured:您的调用缺少 lambda 表达式所需的初始[ captures ] ,即使未捕获任何内容:

myObject.SetXGetter([]{ return MyGlobals.GetX(); });

and I understand this is an area that has improved in more recent C++ versions?我知道这是一个在最近的 C++ 版本中有所改进的领域?

Not in general.一般不会。 It has been expanded to some more complex cases, but the simple cases are pretty much identical to C++11.它已扩展到一些更复杂的情况,但简单的情况与 C++11 几乎相同。

Simplest way to pass a lambda as a method parameter in C++17在 C++17 中将 lambda 作为方法参数传递的最简单方法

The options remain the same:选项保持不变:

  • You can have a template and pass the lambda as-is.您可以拥有一个模板并按原样传递 lambda。
  • Or you can wrap the lambda in a type erasing wrapper such as std::function in which case you can pass it into a non-template function.或者您可以将 lambda 包装在类型擦除包装器中,例如std::function在这种情况下,您可以将其传递给非模板 ZC1C425268E68385D1AB5074C17A94F。
  • Or if the lambda is non-capturing, then it can be converted to a function pointer which can also be passed into a non-template.或者如果 lambda 是非捕获的,则可以将其转换为 function 指针,该指针也可以传递给非模板。

Which one is simplest can vary on context and personal opinion.哪一个最简单可能因上下文和个人意见而异。 Function wrapper works the same in widest number of different cases, to that's a simple choice. Function 包装器在最广泛的不同情况下工作方式相同,这是一个简单的选择。 Function pointer doesn't involve dynamic allocation and is simplest to understand at a low level. Function 指针不涉及动态分配,在底层最容易理解。 Template doesn't involve any sort of wrapping or conversion, but it is a template.模板不涉及任何类型的包装或转换,但它是一个模板。


 this->mLambda = Lambda;

Given that you wish to store the callable as a modifiable member, storing it as a lambda is not an option.鉴于您希望将可调用对象存储为可修改成员,将其存储为 lambda 不是一种选择。 You're left with function wrapper and function pointer.剩下的是 function 包装器和 function 指针。 You can still use a template for the function, but the lambda must be immediately wrapped or converted anyway, so there isn't much to be gained by using a template.您仍然可以为 function 使用模板,但无论如何必须立即包装或转换 lambda,因此使用模板并没有太多好处。

For C++20 and later:对于 C++20 及更高版本:

If you don't intend to store the passed function you can do the following如果您不打算存储传递的 function 可以执行以下操作

void use_it(auto func) {
    func();
}

You can use concepts perhaps to constrain it even more so that it does not except anything but at least a callable.您可能可以使用概念来进一步限制它,以便它除了至少是可调用的之外什么都没有。

If you want to store the argument you will unfortunately still need to name it like the other answers have suggested, and it must be able to convert to the type you specified:如果您想存储参数,不幸的是,您仍然需要像其他答案所建议的那样命名它,并且它必须能够转换为您指定的类型:

#include <functional>

class MyObject {
public:
    void SetXGetter(auto func) {
        mLambda = std::move(func);
    }

private:
    std::function<int()> mLambda;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM