首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为IntoIterator实现Tree<T>?

如何为IntoIterator实现Tree<T>?
EN

Stack Overflow用户
提问于 2021-01-08 06:59:44
回答 2查看 449关注 0票数 4

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

代码语言:javascript
复制
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);
    }
    */
}

got错误: errorE0207:生命周期参数'a不受impl特性的约束

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-08 07:18:45

考虑到您的TreeIter结构和其他一切,您不希望在迭代中使用Tree,您只希望它引用元素。所以你想

代码语言:javascript
复制
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循环中使用它:

代码语言:javascript
复制
let tree = Tree { data: "abc" };
for v in &tree {
      // ^ only iterate via reference
    println!("{:?}", v);
}

游乐场上看到它。参见这个问答,以了解for _ in xfor _ in &x之间的区别。

票数 4
EN

Stack Overflow用户

发布于 2021-01-08 07:36:09

into_iter()的意思是批发获得收藏的所有权。集合被移动到迭代器中,并被迭代所消耗,而不是通过引用借用,而只是查看。该行为由iter()iter_mut()提供。因此,您的代码在概念上是有缺陷的,编译器错误反映了这一点:into_iter不使用已具有任何生存期的集合;它需要一个集合,并立即结束它的生命周期。没有'a让你impl<'a>结束。用正确的思想去实现它,它是有效的。

代码语言:javascript
复制
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()应该被看作是在消耗它的论点.但是“消费”一笔借款实际上并不消耗它所指的东西。这将使用您的迭代器类型,但请注意,这个特性实现不是我们在上面的main中使用的。

代码语言:javascript
复制
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!() }
}

如果你这么做了,这些都会被调用

代码语言:javascript
复制
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
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65624661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档