我有一个生命周期问题,我正在尝试实现一个通过引用返回其项的迭代器,代码如下:
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
有人知道如何解决这个问题并仍然通过引用返回项目吗?
至少这条消息是什么意思:预期的具体生命周期,但找到了绑定(bind)生命周期参数?
最佳答案
Note on the version of Rust used: at the time this question and answer were written, the
Iterator
trait used generics; it has changed to use associated types and is now defined thus:pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; … }
And so the incorrect implementation shown here would be like this:
impl<'a> Iterator for Foo { type Item = &'a u8; fn next<'a>(&'a mut self) -> Option<&'a u8>; }
In practical terms this affects nothing; it is merely that
A
becomesSelf::Item
.
Iterator
的定义因此,特征是:
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>
不应该在那里。为了方便起见并强调这里发生的事情,我将配音为'a
。在 impl block ρ₀ 和'a
上定义在方法 ρ₁ 上定义。 它们不一样。&mut self
的生命周期与性状不同。返回类型的生命周期与特征不同:where
A
是&'ρ₀ u8
,返回类型用于代替A
&'ρ₁ u8
.它预期的是具体的生命周期 ρ₀,但却发现了生命周期 ρ₁。 (我不确定确切地“绑定(bind)”位是什么意思,所以我会保持沉默以免我错了。)
这意味着:您无法将正在迭代的对象的生命周期连接到 &mut self
.相反,它必须绑定(bind)到您正在为其实现特征的类型中的某些东西。举个例子,迭代切片中的项目是通过创建一个连接到基础切片的新迭代器对象来完成的,impl<'a, T> Iterator<&'a T> for Items<'a, T>
.换句话说,迭代特征的设计方式不是,如果你正在生成引用,你就不会在 self
中返回一些东西。 ,而是返回您引用的另一个对象中的内容。
对于您的特定的、大概是简单的示例,您应该停止产生引用,或者更改它以便您的迭代器对象不包含您正在迭代的数据——让它只包含一个引用对它,例如&'a [T]
甚至像 Items<'a, T>
这样的东西.
关于reference - 迭代器通过引用返回项目,生命周期问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24574741/