应用移动lambda闭包(apply move on a lambda closure)

系统教程 行业动态 更新时间:2024-06-14 16:58:30
应用移动lambda闭包(apply move on a lambda closure)

这可能是一个概念性问题。 我正在实现以lambda作为参数的函数。 但是,我无法理解lambda的确切类型。 例如:

auto T = [] () { printf("hello world\n"); }; auto F = move(T); T(); // print "hello world" F(); // print "hello world"

我在调用T之后想到了, T的内容消失了。 换句话说,我期望以下行为:

function<void> T = [] () { printf("hello world\n");}; auto F = move(F); F(); // print "hello world" T(); // throw error

回到最初的问题,将lambda传递给function<void()>的类成员的最佳实践是什么? 我看到很多不同的答案,一些使用const function<void()>&和其他人建议模板F&&

struct Foo { function<void()> f; // Option 1: void set_f(const function<void()>& in) {f=in;} // Option 2: template template <typename F> void set_f(F&& in) { // what to write here??? } }

这两个选项是否足以捕获大多数输入类型?

This might be a conceptual question. I am implementing functions taking lambda as parameters. However, I couldn't understand the exact type of a lambda. For example:

auto T = [] () { printf("hello world\n"); }; auto F = move(T); T(); // print "hello world" F(); // print "hello world"

I thought after calling move on T, the content of T disappeared. In other words, I expect the following behavior:

function<void> T = [] () { printf("hello world\n");}; auto F = move(F); F(); // print "hello world" T(); // throw error

Back to the original question, what is the best practice of passing/assigning a lambda to a class member of function<void()>? I saw many different answers, some using const function<void()>& and others suggesting template F&&

struct Foo { function<void()> f; // Option 1: void set_f(const function<void()>& in) {f=in;} // Option 2: template template <typename F> void set_f(F&& in) { // what to write here??? } }

Are these two options general enough to capture most input types?

最满意答案

您似乎对编译器用lambda表达式做了什么基本的误解。 Lambda表达式转换为具有唯一名称的仿函数。 当你调用lambda时,你只需调用函子的operator() 。

所以你的第一个例子中的lambda会创建类似这样的东西

struct __uniquely_named_lambda { void operator()() const { printf("hello world\n"); } };

如果这个lambda存储任何状态,那么从它移动将移动状态,但你的lambda是无状态的,所以move什么也不做; 你不能剥离operator()的主体并将其移动到其他地方。

例如,这些语句将产生输出4 0 4

std::string s{"Test"}; auto T = [s]() { std::cout << s.size() << ' '; }; // make a copy of s T(); auto F = std::move(T); T(); F();

现场演示


std::function是一个容器,可以接受任何与指定签名匹配的callable ,而lambda就是这样一个可调用的。 当你move std::function ,你正在将它存储的可调用目标移动到目标中。 尝试调用原始目标然后会抛出bad_function_call ,这与move lambda非常不同。


我会写你set_f成员函数为

template <typename F> void set_f(F&& in) { f = std::forward<F>(in); }

您的示例中的F是转发引用,这意味着它将能够接受调用者传递的左值或右值。 然后分配将复制分配或移动分配参数。

You seem to have a basic misunderstanding of what a compiler does with a lambda expression. Lambda expressions are transformed into functors with unique names. When you invoke the lambda you're simply calling the operator() of the functor.

So the lambda in your first example will create something like this

struct __uniquely_named_lambda { void operator()() const { printf("hello world\n"); } };

If this lambda were storing any state, then moveing from it would move the state, but your lambda is stateless, so move does nothing; you can't strip out the body of operator() and move it elsewhere.

For example, these statements will produce the output 4 0 4

std::string s{"Test"}; auto T = [s]() { std::cout << s.size() << ' '; }; // make a copy of s T(); auto F = std::move(T); T(); F();

Live demo


std::function is a container that can accept any callable that matches the specified signature, and your lambda is one such callable. When you move the std::function, you're moving the callable target it stores into the destination. Trying to invoke the target on the original will then throw bad_function_call, this is very different from moveing a lambda.


I'd write you set_f member function as

template <typename F> void set_f(F&& in) { f = std::forward<F>(in); }

F in your example is a forwarding reference, meaning it'll be able to accept either lvalues or rvalues passed by the caller. The assignment will then either copy assign or move assign the argument.

更多推荐

本文发布于:2023-04-15 03:43:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/dzcp/e484804d6d537c912fa0b2a1041cad87.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:apply   lambda   closure   move

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!