迭代器通过引用返回项目,终身问题

use*_*625 12 iterator reference lifetime rust

我有一个终身问题,我正在尝试实现一个迭代器,通过引用返回它的项目,这里是代码:

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

但是这段代码编译不正确,我得到一个与参数生命周期有关的问题,这里是相应的错误:

$ 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
Run Code Online (Sandbox Code Playgroud)

有人知道如何解决这个问题并仍然通过引用返回项目?

至少这个消息意味着什么:预期的具体生命周期,但找到了绑定的生命周期参数

Chr*_*gan 15

关于使用的Rust版本的注意事项:在撰写此问题和答案时,该Iterator特性使用了泛型; 它已更改为使用关联类型,现在定义如下:

pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
    …
}
Run Code Online (Sandbox Code Playgroud)

所以这里显示的错误实现将是这样的:

impl<'a> Iterator for Foo {
    type Item = &'a u8;

    fn next<'a>(&'a mut self) -> Option<&'a u8>;
}
Run Code Online (Sandbox Code Playgroud)

实际上,这没有任何影响; 只是A变成了Self::Item.

因此,Iterator特征的定义是:

pub trait Iterator<A> {
    fn next(&mut self) -> Option<A>;
    …
}
Run Code Online (Sandbox Code Playgroud)

请注意:fn next(&mut self) -> Option<A>.

这是你有的:

impl<'a> Iterator<&'a u8> for Foo {
    fn next<'a>(&'a mut self) -> Option<&'a u8>;
}
Run Code Online (Sandbox Code Playgroud)

请注意:fn next<'a>(&'a mut self) -> Option<&'a u8>.

这里有几个问题:

  1. 您已经引入了一个新的通用参数<'a>,该参数不应该存在.为方便起见并强调这里发生的事情,我将'a在impl块ρ0和'a方法ρ1上定义上定义.他们不一样.

  2. 寿命&mut self与特征的寿命不同.

  3. 返回类型的寿命的特点不同:其中A&'?? u8,返回类型的地方使用A &'?? u8.它期望混凝土寿命ρ0,但发现寿命ρ1.(我不能确定准确的"约束"位意味着什么,所以免得我错了,我会保持沉默就可以了.)

以下是这相当于:您无法连接正在迭代的对象的生命周期&mut self.相反,它必须绑定到您正在实现特征的类型中的某些内容.举个例子,迭代切片中的项目是通过创建一个连接到基础切片的新迭代器对象来完成的impl<'a, T> Iterator<&'a T> for Items<'a, T>.以另一种方式表达,迭代特征的设计方式不是,如果您正在生成引用,则返回内部的内容self,而是返回您引用的另一个对象内的内容.

对于您的特定的,可能是简单的示例,您应该停止产生引用,或者更改它以使您的迭代器对象不包含您迭代的数据 - 让它仅包含对它的引用,例如&'a [T]甚至类似的东西Items<'a, T>.