我有一个lifetime个问题,我试图实现一个迭代器,通过引用返回它的项,下面是代码:

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

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

至少这个信息意味着什么:expected concrete lifetime, but found bound lifetime parameter

推荐答案

Note on the version of Rust used:在写下这个问题和答案时,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>.

这里有几个问题:

  1. 您引入了一个新的通用参数<'a>,该参数不应该存在.为了方便起见,并强调这里发生了什么,我将把impl块ρ上定义的'a命名为₀ 方法ρ中定义的'a₁. They are not the same.

  2. &mut self岁的生命周期 与该性状的生命周期 不同.

  3. 返回类型的生存期与trait不同:如果A&'ρ₀ u8,返回类型使用A代替&'ρ₁ u8.预计混凝土生命周期 ρ₀ 而是找到了生命周期ρ₁. (我不确定"绑定"位是什么意思,所以我会保持沉默,以免出错.)

这意味着:你不能将你正在迭代的对象的生存期连接到&mut self.相反,它必须绑定到您为其实现特征的类型中的某个内容.举个例子,通过创建一个连接到基本切片impl<'a, T> Iterator<&'a T> for Items<'a, T>的新迭代器对象,对切片中的项进行迭代.用另一种方式表示,迭代特征的设计方式不是,如果你正在生成引用,那么你可以在self中返回一些东西,而是在你有引用的另一个对象中返回一些东西.

对于特定的、可能很简单的示例,您应该停止生成引用,或者对其进行修改,使迭代器对象不包含您正在迭代的数据,让它只包含reference,例如&'a [T],甚至类似于Items<'a, T>.

Rust相关问答推荐

if let声明中临时对象的生存期

在Rust中创建可变片段的可变片段的最有效方法是什么?

如何在不安全的代码中初始化枚举 struct

为什么我需要在这个代码示例中使用&

关联类型(类型参数)命名约定

为什么类型需要在这个代码中手动指定,在rust?

为什么`Vec i64`的和不知道是`Option i64`?

如何go 除铁 rust 中路径组件的第一项和最后一项?

在使用#[NO_STD]时,如何在Rust中收到紧急消息?

在rust sqlx中使用ilike和push bind

不能在一个代码分支中具有不变的自身borrow ,而在另一个代码分支中具有可变的self borrow

找不到 .has_func 或 .get_func 的 def

Const 上下文:从 init 函数创建具有 const 通用长度的数组

RUST 中的读写器锁定模式

从字节数组转换为字节元组和字节数组时,为什么 Transmute 会对字节重新排序?

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

OpenGL 如何同时渲染无纹理的四边形和有纹理的四边形

如何使用 Rust Governor 为每 10 秒 10 个请求创建一个 RateLimiter?

Rust 中的生命周期:borrow 的 mut 数据

Rust 中 `Option` 的内存开销不是常量