有没有一种方法可以让merge
函数使用&mut self
,消耗内部枚举值,并在合并时将其推到一个新的Vector上?我一直在与编译器争论这个问题a- PEBKAC,但在哪里?
如果这不可能,可以通过在Val
上实现Clone
trait来解决吗?(但不能通过Copy
trait!)
struct Val();
enum Foo {
One(Val),
Many(Vec<Val>),
}
impl Foo {
pub fn merge(&mut self, other: Self) {
match (*self, other) {
// ^^^^^
// move occurs because `*self` has type `Foo`, which does not implement the `Copy` trait
// cannot move out of `*self` which is behind a mutable reference
//
(Self::One(a), Self::One(b)) => *self = Self::Many(vec![a, b]),
(Self::One(a), Self::Many(mut b)) => {
b.insert(0, a);
*self = Self::Many(b)
}
(Self::Many(mut a), Self::One(b)) => {
a.push(b);
}
(Self::Many(mut a), Self::Many(b)) => {
a.extend(b);
}
};
}
}
4条答案
按热度按时间pu3pd22g1#
我们不能移出
self
,但可以同时用一个空的虚拟对象替换它:8aqjt8rx2#
这里比较棘手的是
One
变量要求在任何时候都有一个值存在,你不能把它的T
取出来,即使是暂时的也不行,因为你必须在那里放一些别的东西来代替它,如果它是One(Option<T>)
,我们可以放一个None
进去,但是对于One(T)
,我们不能这么做。你可以做的是用一个空的
Many
临时替换*self
,然后生成替换对象并覆盖空对象,这样调用者就看不到它了。1hdlvixo3#
为了完整起见,我想再展示一种方法:
(在分配失败的情况下,可能会有一些小的行为差异,但我怀疑是否有人会在意。)
l7wslrjt4#
为了完整起见,另一个避免临时值的解决方案是:
这将消耗
self
并返回一个新的Foo
,因此您可以这样调用它: