当旧的枚举被丢弃时,有没有一种方法可以从 &mut 枚举中提取值?
Is there a way of extracting a value from a &mut enum when the old one is discarded?
我想从模式匹配的可变引用中提取一个值并丢弃旧的。
这是我想出的一个最小示例:
fn main() {
#[derive(Debug)]
enum D<A> {
E1(A),
E2(A, A),
};
trait Zero<A> {
fn zero() -> A;
}
impl<A> D<A> {
pub fn push2(&mut self, e: A) {
match self {
D::E1(e1) => {
*self = D::E2(*e1, e);
}
_ => unimplemented!(),
}
}
pub fn push(&mut self, e: A)
where
A: Zero<A>,
{
match self {
D::E1(e1) => {
let mut r = A::zero();
std::mem::swap(&mut r, e1);
*self = D::E2(e, r);
}
_ => unimplemented!(),
};
}
}
impl Zero<i32> for i32 {
fn zero() -> i32 {
0
}
}
let mut d = D::E1(10);
d.push(11);
println!("{:?}", d);
}
push2
失败:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:17:39
|
17 | *self = D::E2(*e1, e);
| ^^^ cannot move out of borrowed content
我想在不需要 Copy
特性的情况下实现这一点,因为我内部有一些盒装类型,理想情况下我想消除对虚拟变量 (A::zero()
) 的需要。
如果我理解你的代码,A
将是一些数字,因为它实现了 Zero
。数值在 Rust 中实现 Copy
,所以你可以利用它来发挥你的优势:
pub fn push(&mut self, e: A)
where
A: Zero<A> + Copy,
{
match self {
D::E1(e1) => *self = D::E2(e, *e1),
_ => unimplemented!(),
};
}
如果你不想绑定Copy
,你可以按照建议使用std::mem::replace
:
pub fn push(&mut self, e: A)
where
A: Zero<A>,
{
use std::mem::replace;
match self {
D::E1(e1) => *self = D::E2(e, replace(e1, A::zero())),
_ => unimplemented!(),
};
}
这是惯用的方法。
您需要虚拟元素,因为您不能这样做:
D::E1(e1) => *self = D::E2(e, *e1),
原因是编译器首先评估参数,*e1
试图取得借用数据的所有权,但这是被禁止的。
我想从模式匹配的可变引用中提取一个值并丢弃旧的。
这是我想出的一个最小示例:
fn main() {
#[derive(Debug)]
enum D<A> {
E1(A),
E2(A, A),
};
trait Zero<A> {
fn zero() -> A;
}
impl<A> D<A> {
pub fn push2(&mut self, e: A) {
match self {
D::E1(e1) => {
*self = D::E2(*e1, e);
}
_ => unimplemented!(),
}
}
pub fn push(&mut self, e: A)
where
A: Zero<A>,
{
match self {
D::E1(e1) => {
let mut r = A::zero();
std::mem::swap(&mut r, e1);
*self = D::E2(e, r);
}
_ => unimplemented!(),
};
}
}
impl Zero<i32> for i32 {
fn zero() -> i32 {
0
}
}
let mut d = D::E1(10);
d.push(11);
println!("{:?}", d);
}
push2
失败:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:17:39
|
17 | *self = D::E2(*e1, e);
| ^^^ cannot move out of borrowed content
我想在不需要 Copy
特性的情况下实现这一点,因为我内部有一些盒装类型,理想情况下我想消除对虚拟变量 (A::zero()
) 的需要。
如果我理解你的代码,A
将是一些数字,因为它实现了 Zero
。数值在 Rust 中实现 Copy
,所以你可以利用它来发挥你的优势:
pub fn push(&mut self, e: A)
where
A: Zero<A> + Copy,
{
match self {
D::E1(e1) => *self = D::E2(e, *e1),
_ => unimplemented!(),
};
}
如果你不想绑定Copy
,你可以按照建议使用std::mem::replace
:
pub fn push(&mut self, e: A)
where
A: Zero<A>,
{
use std::mem::replace;
match self {
D::E1(e1) => *self = D::E2(e, replace(e1, A::zero())),
_ => unimplemented!(),
};
}
这是惯用的方法。
您需要虚拟元素,因为您不能这样做:
D::E1(e1) => *self = D::E2(e, *e1),
原因是编译器首先评估参数,*e1
试图取得借用数据的所有权,但这是被禁止的。