从迭代器返回的关联类型中提取结构

Pull struct out of associated type returned by iterator

我正在用 Rust 实现双链表。我创建了一个运行良好的迭代器。

#[derive(Clone, Debug)]
pub struct LLCursor<T: Copy> {
    pub cur: Option<Rc<RefCell<Node<T>>>>,
}

impl<T> IntoIterator for List<T>
where
    T: Clone + Copy,
{
    type Item = Rc<RefCell<Node<T>>>;
    type IntoIter = LLCursor<T>;

    fn into_iter(self) -> Self::IntoIter {
        LLCursor {
            cur: self.head.clone(),
        }
    }
}

impl<T> Iterator for LLCursor<T>
where
    T: Copy,
{
    type Item = Rc<RefCell<Node<T>>>;

    fn next(&mut self) -> Option<Rc<RefCell<Node<T>>>> {
        match self.cur.clone() {
            Some(node) => {
                self.cur = node.borrow().next.clone();
                Some(node)
            }
            None => None,
        }
    }
}

我想创建一个函数,可以在迭代时访问链表节点的内容。像这样:

pub fn print(self)
where
    List<T>: IntoIterator,
    <List<T> as IntoIterator>::Item: std::fmt::Debug,
{
    for i in self {
        println!("{:?}", Some(i.borrow().clone().item));
    }
}

错误:

error[E0599]: no method named `borrow` found for associated type `<List<T> as IntoIterator>::Item` in the current scope
   --> src/list.rs:90:51
    |
90  |             println!("{:?}", i.borrow().clone().item);
    |                                ^^^^^^ method not found in `<List<T> as IntoIterator>::Item`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
            `use std::borrow::Borrow;`

我了解 i 在这种情况下属于 <List<T> as IntoIterator>::Item 类型。我是生锈的新手,所以我看不出迭代器 returns 以这种方式关联的类型有何用处。我希望 iOption<Rc<RefCell<Node<T>>>> 类型。有没有一种方法可以将其从关联类型中提取出来,以便我能够访问每个单独节点的元素?

None 的迭代器代码实际上需要 T: Copy,我建议你删除它,因为它混淆了你的问题。那么,既然知道<List<T> as IntoIterator>::Item其实就是T,那么就可以直接使用了:

pub fn print(self) where T: Debug {
    for i in self {
        println!("{:?}", i.borrow().item);
    }
}

我还在打印时删除了 .clone(),因为它是不必要的,并且避免了 T: Clone 约束。看到它在 playground.

上工作

你得到错误的原因是因为约束 List<T>: IntoIteratorItem: Debug 并不意味着 ItemRc<RefCell<_>>。您需要一个额外的约束 T: Copy 才能推断出正确的 IntoIterator 实现。就您演示的代码而言,不存在其他实现,但理论上存在不冲突的实现可能,并且编译器不会进行猜测。

作为旁注,对 Self 类型(此处明确表示为 List<T>)的约束非常少见,除非在特征中,因为您通常知道 Self 需要什么来满足这些限制,并且直接列出它更具描述性。 (即,如果 Self 需要 Clone,但您知道 SelfClone 如果 TClone,您将使用 T: Clone作为约束)。