如何绑定盒装结构的多个字段而不使用"使用移动值"错误?

时间:2015-07-13 19:14:42

标签: struct rust ownership

我试图编写通用的递归数据结构。事实证明,当我想访问一个拥有的struct值的多个字段时,我无法碰壁。

我定义了一个包含列表的结构:

List(None)

空列表由impl<T> List<T> { fn append(self, val: T) -> List<T> { match self { List(None) => List(Some(Box::new(ListNode { val: val, tail: List(None), }))), List(Some(node)) => List(Some(Box::new(ListNode { val: node.val, tail: node.tail.append(val), }))), } } } 表示。

我希望能够附加到列表中:

error[E0382]: use of moved value: `node`
  --> src/main.rs:17:23
   |
16 |                 val: node.val,
   |                      -------- value moved here
17 |                 tail: node.tail.append(val),
   |                       ^^^^^^^^^ value used here after move
   |
   = note: move occurs because `node.val` has type `T`, which does not implement the `Copy` trait

失败并出现可理解的错误:

List(Some(node)) => {
    let ListNode {
        val: nval,
        tail: ntail,
    } = *node;
    List(Some(Box::new(ListNode {
        val: nval,
        tail: ntail.append(val),
    })))
}

我找到了使用结构的多个字段的方法,我找到了 Avoiding partially moved values error when consuming a struct with multiple fields,所以我会这样做:

List(Some(node)) => {
    let ListNode {
        val: ref nval,
        tail: ref ntail,
    } = *node;
    List(Some(Box::new(ListNode {
        val: *nval,
        tail: (*ntail).append(val),
    })))
}

嗯,不,仍然是同样的错误。显然这不再像在链接中那样工作了。

我也尝试过使用refs:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:21:26
   |
21 |                     val: *nval,
   |                          ^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:22:27
   |
22 |                     tail: (*ntail).append(val),
   |                           ^^^^^^^^ cannot move out of borrowed content

这次解构过去了,但是新节点的创建失败了:

String

我错过了一些明显的东西吗?如果没有,访问未通过引用传递的结构的多个字段的正确方法是什么?我使用的是Rust 1.1。

2 个答案:

答案 0 :(得分:6)

>进行了一些奇怪的互动。您需要添加一个解包该框的中间let语句。

& param3

请注意,我将您的函数参数重命名为Box,因此我可以在不重命名的情况下以简短形式编写解构。

Try it out in the playground.

答案 1 :(得分:1)

Non-lexical lifetimes从Rust 2018开始,允许您的原始代码按原样编译:

struct ListNode<T> {
    val: T,
    tail: List<T>
}

struct List<T>(Option<Box<ListNode<T>>>);

impl<T> List<T> {
    fn append(self, val: T) -> List<T> {
        match self {
            List(None) => List(Some(Box::new(ListNode {
                val: val,
                tail: List(None),
            }))),
            List(Some(node)) => List(Some(Box::new(ListNode {
                val: node.val,
                tail: node.tail.append(val),
            }))),
        }
    }
}

fn main() {}