Rust实现合并排序的迭代器

我正在尝试实现一个合并两个排序的迭代器的迭代器。我正在尝试从结构中借用字段的问题。

如何避免此错误?我尝试使用借用的引用,但这似乎无济于事,因为最终我需要移动a_item和b_item的值。

use std::num::Saturating;

pub struct MergeSorted<A, T> {
    a: T,
    b: T,
    a_item: Option<A>,
    b_item: Option<A>,
}

impl<A: Ord, T: Iterator<A>> Iterator<A> for MergeSorted<A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {

        match (self.a_item, self.b_item) {
            (None, None) => None,

            (None, Some(y)) => {
                let result = self.b_item;
                self.b_item = None;
                return result;
            }

            (Some(x), None) => {
                let result = self.a_item;
                self.a_item = self.a.next();
                result
            }

            (Some(x), Some(y)) => {
                if x < y {
                    let result = self.a_item;
                    self.a_item = self.a.next();
                    result
                } else {
                    let result = self.b_item;
                    self.b_item = self.b.next();
                    result
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        // stub
        (10, Some(100))
    }
}

这是特定的错误,对于self.a_item和self.b_item的所有使用都会重复此错误。

error: cannot move out of dereference of `&mut`-pointer
       match (self.a_item, self.b_item) {
              ^~~~~~~~~~~
弗拉基米尔·马特维耶夫(Vladimir Matveev)

第一个问题是这种模式:

let result = self.b_item;
self.b_item = None;
return result;

在第一行之后和第二行self.b_item被移出之前,在其中打个“洞” self(即使我们忘记这self是借来的指针,也不能移出它)。这是不允许的。为了表达这种模式,有一个特殊的功能std::mem称为replace

第二个主要问题是A不可隐式复制,因此,当您尝试匹配type的值时Option<A>,这些值将移出,但&/&mut禁止指针内部移出解决此问题的唯一方法是匹配引用。但是您应该小心,因为借阅规则仅允许您一次只能进行一次可变的借阅。所以,你必须组织一种参考的“流”到self.a_item,并self.b_item通过匹配语句,使用模式绑定。

以下代码进行编译。您也可以直接用调用替换主体中的result变量和Some()用法,但是我认为将值选择和调用分开可以使代码更简洁。我也不能在最后一臂中使用模式,因为引用本身已移入matchmem::replace()mem::replace()Some(x)Some(y)matcha_itemb_item

use std::mem;

pub struct MergeSorted<A, T> {
    a: T,
    b: T,
    a_item: Option<A>,
    b_item: Option<A>,
}

impl<A: Ord, T: Iterator<A>> Iterator<A> for MergeSorted<A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        let result = match (&mut self.a_item, &mut self.b_item) {
            (&None, &None) => None,
            (&None, b_item @ &Some(_)) => Some((b_item, None)),
            (a_item @ &Some(_), &None) => Some((a_item, self.a.next())),
            (a_item @ &Some(_), b_item @ &Some(_)) => Some(
                if a_item.get_ref() < b_item.get_ref() {
                    (a_item, self.a.next())
                } else {
                    (b_item, self.b.next())
                }
            )
        };

        result.and_then(|(dest, value)| mem::replace(dest, value))
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        // stub
        (10, Some(100))
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章