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



我仍然有点困惑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));
}

最新更新