rust - 如何在闭包中使用 FnMut 参数而不移动它或需要复制?

标签 rust closures

我仍然对 Fn-FnMut-FnOnce 事物如何与其他特征一起工作有点困惑。我想从以下遍历树结构的函数中消除 Copy 约束。

pub fn for_each<F>(&mut self, mut f: F)
where
    F: FnMut(&mut Tree<T>) + Copy,
{
    self.children.iter_mut().for_each(|c| c.for_each(f));
    f(self);
}

这样做的原因是我试图传递一个将外部变量修改为 for_each 的闭包,而 Copy 会阻止这种情况发生(E0277)。但是,当我删除 Copy 时,我收到以下错误消息:

error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
  --> src/tree.rs:34:58
   |
30 |     pub fn for_each<F>(&mut self, mut f: F)
   |                                   ----- captured outer variable
...
34 |         self.children.iter_mut().for_each(|c| c.for_each(f));
   |                                                          ^ move occurs because `f` has type `F`, which does not implement the `Copy` trait

error[E0382]: borrow of moved value: `f`
  --> src/tree.rs:35:9
   |
30 |     pub fn for_each<F>(&mut self, mut f: F)
   |                                   ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait
...
34 |         self.children.iter_mut().for_each(|c| c.for_each(f));
   |                                           ---            - variable moved due to use in closure
   |                                           |
   |                                           value moved into closure here
35 |         f(self);
   |         ^ value borrowed here after move
   |
help: consider further restricting this bound
   |
32 |         F: FnMut(&mut Tree<T>) + Copy,
   |                                ^^^^^^

error: aborting due to 2 previous errors

如何解决这个问题?如果这样更容易的话,我也愿意将其转换为迭代器。

最佳答案

原因是 for_each 取得了 f 的所有权。

这意味着,一旦调用 c.for_each(f),您就失去了 f 的所有权,因此以后无法使用 f 。 为了解决这个问题,您可以更改 for_each 函数以获取引用,这样您就可以像这样传递它

pub fn for_each<F>(&mut self, f: &mut F)
where
    F: FnMut(&mut Tree<T>),
{
    // Only a reference is passed into for_each here
    self.children.iter_mut().for_each(|c| c.for_each(f));
    // f can be used again, as reference is reborrowed implicitly
    f(self);
}

或者您也可以(如果可能)将对 f 的调用移到像这样的行

pub fn for_each<F>(&mut self, mut f: F)
where
    F: FnMut(&mut Tree<T>),
{
    // f is used, but ownership is kept
    f(self);
    // ownership of f can now be transferred, as there is no further use of it
    self.children.iter_mut().for_each(|c| c.for_each(f));
}

关于rust - 如何在闭包中使用 FnMut 参数而不移动它或需要复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66845968/

相关文章:

reference - 当我用引用而不是拥有的值调用std::mem::drop时会发生什么?

rust - 为什么 impl trait 不能用于返回多个/条件类型?

rust - 如何修复 : cannot infer an appropriate lifetime for automatic coercion

javascript - 在 Closure 上创建多个元素的监听器

objective-c - 将回调/闭包从 Objective C 转换为 Swift

javascript - Javascript 中的 "Closure"使用对象引用 : where are "private variables" stored?

rust - 使用Rust中的输入初始化全局变量

rust - 由于 "ar crs" "malformed object (unknown load command 1)",无法在 macOS Mojave 上编译 Actix

assembly - 在编译器中实现闭包

ios - 努力理解为什么 "Capturing by reference ensures that runningTotal and amount do not disappear when the call to makeIncrementer ends' ?