Ваш тип итератора Iterator<Item = Self::Item>
, но Iterator
это черта. Черты реализованы структурами, они не существуют сами по себе. У вас также может быть объект ссылочного объекта (&Iterator
) или объект объекта с боксами (Box<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 }
}
}
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
с, а не ссылками. Поскольку они настолько малы, вы можете передать их напрямую.
Это потребляет 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 }
}
}
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
, который у вас есть, поэтому вы только нуждаетесь в не потребляющего варианта. Однако часто бывает, что у вас есть потребительская версия, чтобы вы могли вернуть итератор, не беспокоясь о сроках службы.
OP был чем-то вроде: было бы гораздо удобнее написать это, повторно используя итераторы, которые уже существуют, например, с '[T; 3] '. Но AFAIK, вы не можете выходить из массивов. Вместо этого вы можете это сделать, но это стоит выделить: http://is.gd/IMVLoG – BurntSushi5
Правильно, и вы не можете преобразовать массив в итератор, чтобы сохранить его автономным. Выделение 'Vec', безусловно, является опцией, но, похоже, излишним для * этой * структуры. – Shepmaster
Теперь, когда у нас есть хороший ответ, я отправлю свое. Он немного догадывается о массивах. – ArtemGr