How to implement Iterator and IntoIterator for a simple struct?
有人将如何为以下结构实现
1 2 3 4 5 | struct Pixel { r: i8, g: i8, b: i8, } |
我尝试了以下各种形式,但均未成功。
1 2 3 4 5 6 7 8 | impl IntoIterator for Pixel { type Item = i8; type IntoIter = Iterator<Item=Self::Item>; fn into_iter(self) -> Self::IntoIter { [&self.r, &self.b, &self.g].into_iter() } } |
这段代码给我一个编译错误
1 2 3 4 5 6 7 8 | error[E0277]: the trait bound `std::iter::Iterator<Item=i8> + 'static: std::marker::Sized` is not satisfied --> src/main.rs:7:6 | 7 | impl IntoIterator for Pixel { | ^^^^^^^^^^^^ the trait `std::marker::Sized` is not implemented for `std::iter::Iterator<Item=i8> + 'static` | = note: `std::iter::Iterator<Item=i8> + 'static` does not have a constant size known at compile-time = note: required by `std::iter::IntoIterator` |
您的迭代器类型为
相反,我们创建一个具有已知大小的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | struct Pixel { r: i8, g: i8, b: i8, } impl IntoIterator for Pixel { type Item = i8; type IntoIter = PixelIntoIterator; fn into_iter(self) -> Self::IntoIter { PixelIntoIterator { pixel: self, index: 0, } } } struct PixelIntoIterator { pixel: Pixel, index: usize, } impl Iterator for PixelIntoIterator { type Item = i8; fn next(&mut self) -> Option<i8> { let result = match self.index { 0 => self.pixel.r, 1 => self.pixel.g, 2 => self.pixel.b, _ => return None, }; self.index += 1; Some(result) } } fn main() { let p = Pixel { r: 54, g: 23, b: 74, }; for component in p { println!("{}", component); } } |
这具有返回实际
这会消耗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | impl<'a> IntoIterator for &'a Pixel { type Item = i8; type IntoIter = PixelIterator<'a>; fn into_iter(self) -> Self::IntoIter { PixelIterator { pixel: self, index: 0, } } } struct PixelIterator<'a> { pixel: &'a Pixel, index: usize, } impl<'a> Iterator for PixelIterator<'a> { type Item = i8; fn next(&mut self) -> Option<i8> { let result = match self.index { 0 => self.pixel.r, 1 => self.pixel.g, 2 => self.pixel.b, _ => return None, }; self.index += 1; Some(result) } } |
如果要支持同时创建使用迭代器和非使用迭代器,则可以实现这两个版本。您始终可以引用自己拥有的
这可能有点愚蠢,但是您可以通过将一些现有类型粘合在一起并使用
1 2 3 4 5 6 7 8 9 10 | use std::iter; impl Pixel { fn values(&self) -> impl Iterator<Item = i8> { let r = iter::once(self.r); let b = iter::once(self.b); let g = iter::once(self.g); r.chain(b).chain(g) } } |
首先,
其次,典型的数组
1 2 3 4 | impl<'a, T> IntoIterator for &'a [T; 3] type Item = &'a T type IntoIter = Iter<'a, T> fn into_iter(self) -> Iter<'a, T> |
它需要引用数组(
因此,您不能以尝试的方式使用它。引用的数组必须比返回的迭代器有效。这是Rust编译器告诉您的版本。
Vector具有
附言为了既简单又快速,请返回一个数组,而不是一个迭代器(游戏围栏):
1 2 3 | impl Pixel { fn into_array(self) -> [i8; 3] {[self.r, self.g, self.b]} } |
这样,数组首先移入外部作用域,然后可以从外部作用域的迭代器进行引用:
1 2 3 | for color in &(Pixel {r: 1, g: 2, b: 3}).into_array() { println! ("{}", color); } |