根据the Rust book进一步为包装的向量实施IntoIterator
的示例,我也尝试实现IntoIterator以获取对包装器的引用,如{{ 3}}:
struct VecWrapper(Vec<i32>);
impl VecWrapper {
fn iter(&'static self) -> Iter {
Iter(Box::new(self.0.iter()))
}
}
struct Iter(Box<Iterator<Item = &'static i32>>);
impl Iterator for Iter {
type Item = &'static i32;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
impl IntoIterator for &'static VecWrapper {
type Item = &'static i32;
type IntoIter = Iter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
fn main() {
// let test = vec![1, 2, 3]; // obviously, works
let test = VecWrapper(vec![1, 2, 3]); // not working
for v in &test {
println!("{}", v);
}
}
虽然实现编译,但在main
中使用它的尝试不会出现以下错误:
error[E0597]: `test` does not live long enough
--> src/main.rs:31:14
|
31 | for v in &test {
| ^^^^^
| |
| borrowed value does not live long enough
| argument requires that `test` is borrowed for `'static`
...
34 | }
| - `test` dropped here while still borrowed
这段代码大大简化了我实际想要使用的内容,仅使用'static
生命周期,使用现有的包含类型,并使用i32
作为内部(迭代)类型,但它归结为显示问题。
接受的答案解决了问题的第一部分,即不使用'static
和使用+ 'a
的特征。我仍然遇到实际代码的问题,这是一个LazyList
实现。我已将其发布为the following code (Playground link)。
答案 0 :(得分:6)
您已正确实现迭代器,以便在程序的整个长度生存的VecWrapper
'static
的引用中实现'a
生命周期。
您希望拥有通用生命周期。然后,这个生命周期将被提供一个具体的生命周期,每个实例都是唯一的。通常,我们很懒,只给这个生命周期命名为struct VecWrapper(Vec<i32>);
impl VecWrapper {
fn iter(&self) -> Iter {
Iter(Box::new(self.0.iter()))
}
}
struct Iter<'a>(Box<Iterator<Item = &'a i32> + 'a>);
impl<'a> Iterator for Iter<'a> {
type Item = &'a i32;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
impl<'a> IntoIterator for &'a VecWrapper {
type Item = &'a i32;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
fn main() {
let test = VecWrapper(vec![1, 2, 3]); // not working
for v in &test {
println!("{}", v);
}
}
:
Box<Iterator<Item = &'a i32> + 'a>
重要变化:
+ 'a
- Item
已添加。这是必需的,因为特征对象将假定没有内部值引用具有短寿命的任何内容。&'a i32
类型现在为<'a>
。struct Iter<'a>(std::slice::Iter<'a, i32>);
)。另见:
通常,在这里使用特质对象并不是理由。我直接嵌入了迭代器:
SELECT DISTINCT instructors.name AS name,
substring(sections.course,1,4) AS courseCode
FROM instructors
JOIN teaches ON instructors.id = teaches.instructor_id
JOIN schedules ON teaches.schedule_id = schedules.id
JOIN sections ON schedules.section_id = sections.id
这避免了需要任何间接,在这种情况下无论如何都是未使用的。此外,它更明显地结合了一生。