[英]Iterator returning items by reference, lifetime issue
我有一个终身问题,我正在尝试实现一个通过引用返回其项目的迭代器,这是代码:
struct Foo {
d: [u8; 42],
pos: usize
}
impl<'a> Iterator<&'a u8> for Foo {
fn next<'a>(&'a mut self) -> Option<&'a u8> {
let r = self.d.get(self.pos);
if r.is_some() {
self.pos += 1;
}
r
}
}
fn main() {
let mut x = Foo {
d: [1; 42],
pos: 0
};
for i in x {
println!("{}", i);
}
}
但是这段代码没有正确编译,我遇到了一个与参数生命周期相关的问题,这是相应的错误:
$ rustc test.rs
test.rs:8:5: 14:6 error: method `next` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter
test.rs:8 fn next<'a>(&'a mut self) -> Option<&'a u8> {
test.rs:9 let r = self.d.get(self.pos);
test.rs:10 if r.is_some() {
test.rs:11 self.pos += 1;
test.rs:12 }
test.rs:13 r
...
test.rs:8:49: 14:6 note: expected concrete lifetime is the lifetime 'a as defined on the block at 8:48
test.rs:8 fn next<'a>(&'a mut self) -> Option<&'a u8> {
test.rs:9 let r = self.d.get(self.pos);
test.rs:10 if r.is_some() {
test.rs:11 self.pos += 1;
test.rs:12 }
test.rs:13 r
...
error: aborting due to previous error
有人知道如何解决这个问题并仍然通过引用返回项目吗?
至少这条消息是什么意思:预期的具体生命周期,但发现绑定的生命周期参数?
注意所使用的 Rust 版本:在编写此问题和答案时,
Iterator
trait 使用泛型; 它已更改为使用关联类型,现在定义如下:pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; … }
所以这里显示的不正确的实现是这样的:
impl<'a> Iterator for Foo { type Item = &'a u8; fn next<'a>(&'a mut self) -> Option<&'a u8>; }
实际上,这没有任何影响; 只是
A
变成了Self::Item
。
Iterator
trait 的定义是这样的:
pub trait Iterator<A> {
fn next(&mut self) -> Option<A>;
…
}
请注意: fn next(&mut self) -> Option<A>
。
这是你所拥有的:
impl<'a> Iterator<&'a u8> for Foo {
fn next<'a>(&'a mut self) -> Option<&'a u8>;
}
请注意: fn next<'a>(&'a mut self) -> Option<&'a u8>
。
这里有几个问题:
您引入了一个新的通用参数<'a>
,它不应该在那里。 为方便起见并强调这里发生的事情,我将在 impl 块 ρ₀ 上定义的'a
和在方法 ρ₁ 上定义的'a
配音。 她们不一样。
&mut self
的生命周期&mut self
trait 的生命周期不同。
返回类型的生命周期与 trait 不同:其中A
是&'ρ₀ u8
,返回类型用于代替A
&'ρ₁ u8
。 它预期的具体寿命为 ρ₀,但结果却是寿命 ρ₁。 (我不确定“绑定”位的确切含义,所以我会保持沉默,以免我错了。)
这就是它的含义:您无法将正在迭代的对象的生命周期连接到&mut self
。 相反,它必须绑定到您正在为其实现特征的类型中的某些内容。 举个例子,迭代切片中的项目是通过创建一个连接到基本切片的新迭代器对象来完成的, impl<'a, T> Iterator<&'a T> for Items<'a, T>
。 换句话说,迭代特征的设计方式不是,如果您正在生成引用,则返回self
内部的某些内容,而是返回您引用的另一个对象内部的某些内容。
对于您的特定的,大概是简单的示例,您应该停止产生引用,或者更改它,以便您的迭代器对象不包含您正在迭代的数据——让它只包含对它的引用,例如&'a [T]
甚至像Items<'a, T>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.