Rust 如何实现树的迭代器<;T>;?
我尝试为Tree实现IntoIterator,然后我可以使用“for in Tree”,否则我必须在TreeIter{…}中编写for,但是生命周期错误:Rust 如何实现树的迭代器<;T>;?,rust,iterator,lifetime,Rust,Iterator,Lifetime,我尝试为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, } imp
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);
}
*/
}
考虑到您的
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 uux
与for uux
之间的区别鉴于树的结构和其他一切,您不希望在迭代时使用树,只希望它引用元素。所以你想要
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 uux
与for uux
的区别。Inuiter()
旨在批量获得收藏的所有权。集合被移动到迭代器中,并由迭代使用,而不是通过引用借用,只是查看。该行为由iter()
和iter\u mut()
提供。因此,您的代码在概念上是有缺陷的,编译器错误反映出:into\u iter
不会借用集合已有的生命周期;它需要一个集合,并在那里结束它的生命周期。没有一个'a
供您导入。\u iter()
是指批量获得收藏的所有权。集合被移动到迭代器中,并由迭代使用,而不是通过引用借用,只是查看。该行为由iter()
和iter\u mut()
提供。因此,您的代码在概念上是有缺陷的,编译器错误反映出:into\u iter
不会借用集合已有的生命周期;它需要一个集合,并在那里结束它的生命周期。没有一个'a
可以让你执行。这篇文章的另一个答案是一个消耗性迭代器。一个功能齐全的收藏通常会同时具备这两种功能;请看,有一个用于Vec
,一个用于&Vec
,还有一个用于&mut-Vec
。这篇文章的另一个答案建议使用消耗迭代器。一个功能齐全的收藏通常会同时具备这两种功能;请参阅,有一个用于Vec
,一个用于&Vec
,还有一个用于&mut-Vec
。
let tree = Tree { data: "abc" };
for v in &tree {
// ^ only iterate via reference
println!("{:?}", v);
}
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) }
}
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
}