Pri*_*rgo 16 iterator traits rust
我想实现Iterator包含可迭代字段的结构的特征。迭代我的结构应该产生与迭代该字段获得的相同结果。这就是我想要的(显然不起作用):
struct Foo {
bar: Vec<char>,
}
impl Iterator for Foo {
type Item: &char; // Error: expected named lifetime parameter
fn next(&mut self) -> Option<Self::Item> {
self.bar.iter().next()
}
}
Run Code Online (Sandbox Code Playgroud)
为了避免该错误,我尝试插入生命周期:
use std::marker::PhantomData;
struct Foo<'a> {
bar: Vec<char>,
phantom: &'a PhantomData<char> // not sure what to put inside < .. >
}
impl<'a> Iterator for Foo<'a> {
type Item = &'a char;
fn next(&mut self) -> Option<Self::Item> {
self.bar.iter().next() // again, several errors about lifetimes
}
}
Run Code Online (Sandbox Code Playgroud)
我如何实现Iterator这样一个结构的特征?
Loc*_*cke 27
Iterator创造一个的东西和创造一个东西之间有很大的区别Iterator。例如,Vec<char>可以产生一个迭代器,但本身不是迭代器。以下是两者的几个简单示例,因此您有望找到适合您的用例的东西。
对于您的情况来说,最简单的方法是只在Deref现场实施并让其Vec<char>处理。或者,您可以为 编写一个包装函数bar.iter()。
pub struct Foo {
bar: Vec<char>,
}
impl Deref for Foo {
type Target = Vec<char>;
fn deref(&self) -> &Self::Target {
&self.bar
}
}
let foo = Foo { bar: vec!['a', 'b', 'c', 'd'] };
// deref is implicitly called so foo.iter() represents foo.bar.iter()
for x in foo.iter() {
println!("{:?}", x);
}
Run Code Online (Sandbox Code Playgroud)
以下是您如何为Vec<char>. 请注意如何将其Vec存储为引用而不是拥有的值。这样 Rust 就可以解决寿命限制。通过在迭代器的生命周期内保留不可变的引用,我们保证该迭代器生成的引用也可以在该生命周期内持续存在。如果我们使用拥有的值,我们只能保证元素引用的生命周期持续到下一次将可变引用传递给迭代器为止。或者换句话说,每个值只能持续到next再次调用为止。然而,即使这也需要夜间功能才能正确表达。
pub struct SimpleIter<'a> {
values: &'a Vec<char>,
index: usize,
}
impl<'a> Iterator for SimpleIter<'a> {
type Item = &'a char;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.values.len() {
return None
}
self.index += 1;
Some(&self.values[self.index - 1])
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个包装另一个迭代器的通用迭代器的简单示例。
// Add ?Sized so Foo can hold a dynamically sized type to satisfy IntoFoo
struct Foo<I: ?Sized> {
bar: I,
}
impl<I: Iterator> Iterator for Foo<I> {
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
println!("Iterating through Foo");
self.bar.next()
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以通过创建一个易于使用的特征来更喜欢它Foo。
pub trait IntoFoo {
fn iter_foo(self) -> Foo<Self>;
}
// Add an iter_foo() method for all existing iterators
impl<T: Iterator> IntoFoo for T {
fn iter_foo(self) -> Foo<Self> {
Foo { bar: self }
}
}
let values = vec!['a', 'b', 'c', 'd'];
// Get default iterator and wrap it with our foo iterator
let foo: Foo<std::slice::Iter<'_, char>> = values.iter().iter_foo();
for x in foo {
println!("{:?}", x);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6053 次 |
| 最近记录: |