gpt4 book ai didi

iterator - 如何为简单结构实现 Iterator 和 IntoIterator?

转载 作者:行者123 更新时间:2023-11-29 07:40:18 25 4
gpt4 key购买 nike

如何为以下结构实现 IteratorIntoIterator 特征?

struct Pixel {
r: i8,
g: i8,
b: i8,
}

我已经尝试了以下各种形式但没有成功。

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()
}
}

这段代码给我一个编译错误

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`

最佳答案

您的迭代器类型是 Iterator<Item = Self::Item> ,但是Iterator是一种特质。特征由结构实现,它们本身并不存在。您还可以有一个引用特征对象 (&Iterator)、一个盒装特征对象 (Box<Iterator>) 或一个匿名特征实现 (impl Iterator),所有这些都有已知的大小。

相反,我们创建一个 PixelIntoIterator具有已知大小并实现 Iterator本身:

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,
}
}
}

pub 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);
}
}

这有返回实际 i8 的好处s,不是引用。由于这些很小,您还不如直接通过它们。

这消耗了 Pixel .如果您引用了 Pixel ,您还需要实现一个不使用它的迭代器:

impl<'a> IntoIterator for &'a Pixel {
type Item = i8;
type IntoIter = PixelIterator<'a>;

fn into_iter(self) -> Self::IntoIter {
PixelIterator {
pixel: self,
index: 0,
}
}
}

pub 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)
}
}

如果您想支持创建消费迭代器和非消费迭代器,您可以实现这两个版本。您始终可以引用 Pixel你拥有,所以你只需要非消费变体。但是,拥有一个消费版本通常很好,这样您就可以返回迭代器而不必担心生命周期。


it'd be much more convenient to write this by reusing iterators that already exists, e.g., with [T; 3]

从 Rust 1.51 开始,您可以利用 array::IntoIter :

impl IntoIterator for Pixel {
type Item = i8;
type IntoIter = std::array::IntoIter<i8, 3>;

fn into_iter(self) -> Self::IntoIter {
std::array::IntoIter::new([self.r, self.b, self.g])
}
}

在以前的版本中,这可能有点傻,但您可以通过将一些现有类型粘合在一起并使用 impl Iterator 来避免创建自己的迭代器类型。 :

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)
}
}

关于iterator - 如何为简单结构实现 Iterator 和 IntoIterator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30218886/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com