我可以为自定义类型实现IntoIterator
,但当IntoIterator
绑定到自定义特征时,我无法实现该特征。
下面的代码显示了问题。当为自定义类型(FakeReader
(实现IntoIterator
时,一切都很好。然而,当我尝试为该类型实现BmpReader
时,编译器似乎会获取IntoIterator
的内部impl
,并要求我的自定义类型为Iterator
。
use core::iter::Iterator;
/// The trait that I'm designing
pub trait BmpReader : IntoIterator {
const INTERNAL_BUFFER_SIZE: usize;
}
// Uncomment to see error
//impl BmpReader for FakeReader {
// const INTERNAL_BUFFER_SIZE: usize = 20;
//}
impl<'a> IntoIterator for &'a FakeReader {
type Item = &'a [u8];
type IntoIter = FakeReaderIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter{
reader: &self,
index: 0,
}
}
}
struct FakeReader {
buffer: [u8; 20],
}
pub struct FakeReaderIterator<'a> {
reader: &'a FakeReader,
index: usize
}
impl<'a> Iterator for FakeReaderIterator<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.reader.buffer.len() {
return None;
}
let result = &self.reader.buffer[self.index..self.index+1];
self.index += 1;
Some(result)
}
}
fn main() {
let mut reader = FakeReader {
buffer: [0u8; 20]
};
let _= reader.buffer.iter_mut().enumerate().map(|(i,v)| *v = i as u8).count();
for i in &reader {
println!("{:?}", i)
}
}
取消对有问题的impl
块的注释会导致以下错误:
error[E0277]: `FakeReader` is not an iterator
--> src/main.rs:9:6
|
9 | impl BmpReader for FakeReader {
| ^^^^^^^^^ `FakeReader` is not an iterator
|
= help: the trait `Iterator` is not implemented for `FakeReader`
= help: the trait `IntoIterator` is implemented for `&'a FakeReader`
= note: required because of the requirements on the impl of `IntoIterator` for `FakeReader`
note: required by a bound in `BmpReader`
--> src/main.rs:4:23
|
4 | pub trait BmpReader : IntoIterator {
| ^^^^^^^^^^^^ required by this bound in `BmpReader`
游乐场连接
当创建具有特征绑定的特征时,您绑定了Self
来实现该特征,但在本例中,&FakeReader
实现了IntoIterator
,因此您不能为FakeReader
实现BmpReader
,但可以为&FakeReader
实现。你可以写
impl<'a> BmpReader for &'a FakeReader {
const INTERNAL_BUFFER_SIZE: usize = 20;
}
访问常量意味着写入
let size = <&FakeReader>::INTERNAL_BUFFER_SIZE;
并在BmpReader
:上创建一个通用函数
fn foo<T: BmpReader>(a: T) {
let _size = T::INTERNAL_BUFFER_SIZE;
let _iter = a.into_iter();
}
fn main() {
let reader = FakeReader {
buffer: [0u8; 20]
};
test(&reader);
}
另一种解决方案是绑定&Self
以实现特性的IntoIterator
:
pub trait BmpReader
where for <'a> &'a Self: IntoIterator
{
const INTERNAL_BUFFER_SIZE: usize;
}
impl BmpReader for FakeReader {
const INTERNAL_BUFFER_SIZE: usize = 20;
}
(for<'a> &'a Self: IntoIterator
是@Chayim Friedman的建议(
您现在可以直接在FakeReader
:上访问常量
let size = FakeReader::INTERNAL_BUFFER_SIZE;
但是在BmpReader
上创建泛型函数需要指定绑定:
fn foo<T: BmpReader>(a: &T)
where for <'a> &'a T: IntoIterator
{
let _size = T::INTERNAL_BUFFER_SIZE;
let _iter = a.into_iter();
}
fn main() {
let reader = FakeReader {
buffer: [0u8; 20]
};
foo(&reader);
}
Bot解决方案是有效的,请选择最适合您需求的解决方案,并使代码最具可读性/可维护性。