繁体   English   中英

如何为树实现 IntoIterator<t> ?</t>

[英]How to implement IntoIterator for Tree<T>?

我尝试为 Tree 实现 IntoIterator,然后我可以使用“for in Tree”,否则我必须在 TreeIter{...} 中写 for,但是生命周期错误:

use std::iter::IntoIterator;

#[derive(Debug)]
struct Tree<T> {
    data: T,
}

struct TreeIter<'a, T> {
    tree: &'a Tree<T>,
    count: i32,
}

impl<'a, T> IntoIterator for Tree<T> {
    type Item = &'a Tree<T>;
    type IntoIter = TreeIter<'a, T>;

    fn into_iter(&'a self) -> Self::IntoIter {
        TreeIter { tree: &self, count: 0 }
    }
}

impl<'a, T> Iterator for TreeIter<'a, T>
{
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        if self.count > 5 {
            return None;
        } else {
            return Some(&self.tree.data);
        }
    }
}

fn main() {
    let tree = Tree { data: "abc" };

    for v in tree {
        println!("{:?}", v);
    }

    /*
    let treeiter = TreeIter{tree: &tree, count: 0};
    for (i, &v) in treeiter.enumerate() {
        println!("{}: {}", i, v);
    }
    */
}

得到错误:错误[E0207]:生命周期参数'a不受impl trait约束

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
  --> test-iter/src/main.rs:13:6
   |
13 | impl<'a, T> IntoIterator for Tree<T> {
   |      ^^ unconstrained lifetime parameter

鉴于您的TreeIter结构和其他所有内容,您不想在迭代时使用Tree ,您只希望它引用元素。 所以你要

impl<'a, T> IntoIterator for &'a Tree<T> {
                          // ^^^^^^^^^^^ implement for references to Trees
    type Item = &'a T;
             // ^^^^^ this needs to match Iterator::Item for TreeIter
    type IntoIter = TreeIter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
              // ^^^^ self is a &'a Tree<T>
        TreeIter { tree: self, count: 0 }
    }
}

然后你可以像这样在 for 循环中使用它:

let tree = Tree { data: "abc" };
for v in &tree {
      // ^ only iterate via reference
    println!("{:?}", v);
}

操场上看到它。 请参阅此问答,了解for _ in xfor _ in &x之间的区别。

into_iter()旨在批发获取集合的所有权。 集合被移动到迭代器中并被迭代消耗,而不是通过引用借用并简单地查看。 该行为由iter()iter_mut()提供。 因此,您的代码在概念上存在缺陷,并且编译器错误反映了这一点: into_iter不会借用一个集合,它已经具有任何生命周期; 它需要一个集合并在那时和那里结束它的生命周期。 没有'a让你impl<'a>结束。 以正确的想法实施它并且它有效

struct IntoIter<T> { // e.g. same convention as std::vec::IntoIter
    tree: Tree<T>,
    pos: i32,
}
// due to your dummy implementation, we need T: Copy, but a real implementation shouldn't need it
impl<T: Copy> IntoIterator for Tree<T> {
    type Item = T; // why would iterating over a tree give you trees?
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter { tree: self, pos: 0 }
    }
}
impl<T: Copy> Iterator for IntoIter<T> {
    type Item = T; // iterating over an IntoIter should give values moved out of the container (in this case we're copying the same value a few times and pretending they were moved)
    fn next(&mut self) -> Option<Self::Item> {
        if self.pos < 5 {
            self.pos += 1;
            Some(self.tree.data)
        } else {
            None
        }
    }
}

fn main() {
    for i in (Tree { data: 1 }) { println!("{}", i) }
}

请注意,通常也为集合的借用提供IntoIterator 同样, into_iter()应该被视为消耗它的论点......但是“消耗”借用实际上并没有消耗它所指的东西。 将使用您的迭代器类型,但请注意,此 trait 实现不是我们在上述main中使用的。

struct Iter<'a, T> {
    tree: &'a Tree<T>,
    pos: i32
}
impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> { todo!() }
}
impl<'a, T> IntoIterator for &'a Tree<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;
    fn into_iter(self) -> Iter<'a, T> { todo!() }
}

struct IterMut<'a, T> {
    tree: &'a mut Tree<T>,
    pos: i32
}
impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> { todo!() }
}
impl<'a, T> IntoIterator for &'a mut Tree<T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;
    fn into_iter(self) -> IterMut<'a, T> { todo!() }
}

如果你这样做,这些将被调用

fn main() {
    let mut tree = Tree { data: 1 };
    for i in &tree { println!("{}", i) } // IntoIter for borrow
    for i in &mut tree { println!("{}", i) } // IntoIter for mutable borrow
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM