我是否错误地实现了 IntoIterator 作为参考,或者这是一个应该报告的 Rust 错误?
Am I incorrectly implementing IntoIterator for a reference or is this a Rust bug that should be reported?
根据 the Rust book, I am also trying to implement IntoIterator for a reference to the wrapper, as per the following code (Playground link):
进一步实现包装向量 IntoIterator
的示例
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
实现。我已将其发布为 .
您已经正确实现了对 VecWrapper
的引用的迭代器, 在程序的整个长度 — 'static
生命周期中存在。
您可能希望拥有通用的生命周期。然后将为该生命周期提供一个具体的生命周期,对于每个实例化都是唯一的。通常,我们很懒惰,只是给这一生起个名字'a
:
struct VecWrapper(Vec<i32>);
impl VecWrapper {
fn iter(&self) -> Iter {
Iter(Box::new(self.0.iter()))
}
}
struct Iter<'a>(Box<dyn 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]);
for v in &test {
println!("{}", v);
}
}
重要变化:
Box<dyn Iterator<Item = &'a i32> + 'a>
- 添加了 + 'a
。这是必需的,因为 trait 对象 将假设没有内部值引用任何短生命周期的东西。
Item
类型现在是 &'a i32
。
- 通用生命周期在许多地方声明并在许多其他地方提供 (
<'a>
)。
另请参阅:
通常情况下,没有理由在这里使用特征对象。我只是直接嵌入迭代器:
struct Iter<'a>(std::slice::Iter<'a, i32>);
这避免了任何间接的需要,无论如何在这种情况下都没有使用。此外,它更明显地耦合了生命周期。
根据 the Rust book, I am also trying to implement IntoIterator for a reference to the wrapper, as per the following code (Playground link):
进一步实现包装向量IntoIterator
的示例
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
实现。我已将其发布为
您已经正确实现了对 VecWrapper
的引用的迭代器, 在程序的整个长度 — 'static
生命周期中存在。
您可能希望拥有通用的生命周期。然后将为该生命周期提供一个具体的生命周期,对于每个实例化都是唯一的。通常,我们很懒惰,只是给这一生起个名字'a
:
struct VecWrapper(Vec<i32>);
impl VecWrapper {
fn iter(&self) -> Iter {
Iter(Box::new(self.0.iter()))
}
}
struct Iter<'a>(Box<dyn 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]);
for v in &test {
println!("{}", v);
}
}
重要变化:
Box<dyn Iterator<Item = &'a i32> + 'a>
- 添加了+ 'a
。这是必需的,因为 trait 对象 将假设没有内部值引用任何短生命周期的东西。Item
类型现在是&'a i32
。- 通用生命周期在许多地方声明并在许多其他地方提供 (
<'a>
)。
另请参阅:
通常情况下,没有理由在这里使用特征对象。我只是直接嵌入迭代器:
struct Iter<'a>(std::slice::Iter<'a, i32>);
这避免了任何间接的需要,无论如何在这种情况下都没有使用。此外,它更明显地耦合了生命周期。