Trait 实现了 Iterator,但不能将实现我的 trait 的结构用作 Iterator
Trait implements Iterator, but cannot use a struct implementing my trait as an Iterator
我有一个特性,我想说如果一个结构实现了这个特性,那么它也可以充当 Iterator
。但是,当我尝试将结构用作迭代器时遇到编译器错误。
我正在编写一个库来从许多不同的文件格式中读取相同类型的数据。我想创建一个通用的 "reader" 特性,它将 return 适当的生锈对象。我想说每个 reader 都可以作为迭代器运行,产生该对象。
这是代码
/// A generic trait for reading u32s
trait MyReader {
fn get_next(&mut self) -> Option<u32>;
}
/// Which means we should be able to iterate over the reader, yielding u32s
impl Iterator for MyReader {
type Item = u32;
fn next(&mut self) -> Option<u32> {
self.get_next()
}
}
/// Example of a 'reader'
struct MyVec {
buffer: Vec<u32>,
}
/// This can act as a reader
impl MyReader for MyVec {
fn get_next(&mut self) -> Option<u32> {
self.buffer.pop()
}
}
fn main() {
// Create a reader
let mut veccy = MyVec { buffer: vec![1, 2, 3, 4, 5] };
// Doesn't work :(
let res = veccy.next();
}
编译器输出:
rustc 1.15.0 (10893a9a3 2017-01-19)
error: no method named `next` found for type `MyVec` in the current scope
--> <anon>:31:21
|
31 | let res = veccy.next();
| ^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item `next`, perhaps you need to implement one of them:
= help: candidate #1: `std::iter::Iterator`
= help: candidate #2: `std::iter::ZipImpl`
= help: candidate #3: `std::str::pattern::Searcher`
Here 是 rust playground 上的代码。
在我看来,既然 MyVec
实现了 MyReader
,那么它应该可以用作迭代器,因此我应该能够在其上调用 .next()
。既然我实现了 MyReader
,那么我应该免费得到一个 Iterator
的实现,对吧? impl Iterator for ...
行显示 Iterator
在范围内,所以我无法理解错误的来源。
这条线并不像你想的那样。
impl Iterator for MyReader {
这为 trait object MyReader
实现了 Iterator
。您想要的是为每个也实现 MyReader
的类型实现 Iterator
。不幸的是,由于一致性规则,这是不可能的。
在 Rust 中,您只能在定义特征的板条箱或定义要实现它的类型的板条箱中实现特征。 (对于泛型类型,事情有点复杂,但这是基本思想。)在这种情况下,Iterator
是标准库中的特征,因此您无法在任意类型上实现它没有定义。如果您考虑一下,这是有道理的,否则如果其中一种类型具有 Iterator
的 pre-existing 实现,您会感到歧义 - 将使用哪个?
一个解决方案是将实现 MyReader
的类型包装在一个新类型中,然后在其上实现 Iterator
。由于您自己定义了新类型,因此您可以在其上自由实现 Iterator
。
我有一个特性,我想说如果一个结构实现了这个特性,那么它也可以充当 Iterator
。但是,当我尝试将结构用作迭代器时遇到编译器错误。
我正在编写一个库来从许多不同的文件格式中读取相同类型的数据。我想创建一个通用的 "reader" 特性,它将 return 适当的生锈对象。我想说每个 reader 都可以作为迭代器运行,产生该对象。
这是代码
/// A generic trait for reading u32s
trait MyReader {
fn get_next(&mut self) -> Option<u32>;
}
/// Which means we should be able to iterate over the reader, yielding u32s
impl Iterator for MyReader {
type Item = u32;
fn next(&mut self) -> Option<u32> {
self.get_next()
}
}
/// Example of a 'reader'
struct MyVec {
buffer: Vec<u32>,
}
/// This can act as a reader
impl MyReader for MyVec {
fn get_next(&mut self) -> Option<u32> {
self.buffer.pop()
}
}
fn main() {
// Create a reader
let mut veccy = MyVec { buffer: vec![1, 2, 3, 4, 5] };
// Doesn't work :(
let res = veccy.next();
}
编译器输出:
rustc 1.15.0 (10893a9a3 2017-01-19)
error: no method named `next` found for type `MyVec` in the current scope
--> <anon>:31:21
|
31 | let res = veccy.next();
| ^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item `next`, perhaps you need to implement one of them:
= help: candidate #1: `std::iter::Iterator`
= help: candidate #2: `std::iter::ZipImpl`
= help: candidate #3: `std::str::pattern::Searcher`
Here 是 rust playground 上的代码。
在我看来,既然 MyVec
实现了 MyReader
,那么它应该可以用作迭代器,因此我应该能够在其上调用 .next()
。既然我实现了 MyReader
,那么我应该免费得到一个 Iterator
的实现,对吧? impl Iterator for ...
行显示 Iterator
在范围内,所以我无法理解错误的来源。
这条线并不像你想的那样。
impl Iterator for MyReader {
这为 trait object MyReader
实现了 Iterator
。您想要的是为每个也实现 MyReader
的类型实现 Iterator
。不幸的是,由于一致性规则,这是不可能的。
在 Rust 中,您只能在定义特征的板条箱或定义要实现它的类型的板条箱中实现特征。 (对于泛型类型,事情有点复杂,但这是基本思想。)在这种情况下,Iterator
是标准库中的特征,因此您无法在任意类型上实现它没有定义。如果您考虑一下,这是有道理的,否则如果其中一种类型具有 Iterator
的 pre-existing 实现,您会感到歧义 - 将使用哪个?
一个解决方案是将实现 MyReader
的类型包装在一个新类型中,然后在其上实现 Iterator
。由于您自己定义了新类型,因此您可以在其上自由实现 Iterator
。