rust 有没有一种好的方法可以在保持所有权的同时使用带有指针的枚举

pu82cl6c  于 2023-04-30  发布在  其他
关注(0)|答案(2)|浏览(116)

我有这个enum:

enum VecP<'a> {
    Imut(&'a Vec<usize>),
    Mut(&'a mut Vec<usize>)
}

我想把它传递给一个函数,以后可以再次使用它(或者在循环中使用它)
我想传递它的函数接受一个VecP,我不能改变它接受指针。
如果我这样做:

let vp = VecP::Imut(&v);
func(vp); // ownership is given here and I can't use it anymore

我想出的解决方案是:

match vp {
    VecP::Mut(v) => {
        func(VecP::Mut(v)); // I don't loose ownership to v cuz it's a pointer
        vp = VecP::Mut(v); // because of the reassignment I can continue to use `vp`
    }
    VecP::Imut(v) => {
        func(VecP::Imut(v));
        vp = VecP::Imut(v);
    }
}

然而,这有点乏味,(特别是如果func调用更复杂或者枚举有更多选项)我想知道是否有更好的方法,也许像克隆方法?
我能想到的最好的办法是写一个宏来生成这些代码,但这似乎有点过头了
playground

k97glaaz

k97glaaz1#

一种选择是向VecP添加一个方法,为您进行匹配和重建:

enum VecP<'a> {
    Imut(&'a Vec<usize>),
    Mut(&'a mut Vec<usize>),
}

impl VecP<'_> {
    fn reborrow(&mut self) -> VecP {
        match *self {
            VecP::Imut(v) => VecP::Imut(v),
            VecP::Mut(ref mut v) => VecP::Mut(*v),
        }
    }
}

fn func(_: VecP) {
    // something
}

fn main() {
    let v = vec![1, 2, 3];
    let mut vp = VecP::Imut(&v);
    func(vp.reborrow());
    let _ = vp;
}

Playground
这隐藏了reborrow()方法中的丑陋之处,因此实际的函数调用看起来并不太糟糕。reborrow()的代码比你的版本简单一点。您可以重新借用 Package 的引用,而不是将它们移出枚举。
不管怎样,这种尴尬似乎是由func()的接口错误引起的。修复接口将是我的第一次尝试,但如果没有机会,你必须绕过这个问题。

wz1wpwve

wz1wpwve2#

你可以重构你的解决方案不那么繁琐:

if let VecP::Imut(v) = vp {
    func(VecP::Imut(v));
}
if let VecP::Mut(v) = vp {
    func(VecP::Mut(v));
}

Playground

相关问题