如何在结构内容上返回对迭代器的适当生存期的引用?

时间:2018-12-06 09:39:10

标签: rust lifetime

我正尝试在二维网格上实现迭代器,如下所示(这是对更为复杂的设置的简化):

struct Grid {
    width: usize,
    height: usize,
}

impl Grid {
    fn new(width: usize, height: usize) -> Grid {
        Grid { width, height }
    }

    fn iter<'a>(&'a self) -> &'a impl Iterator<Item = (usize, usize)> {
        let i = (0..self.height).flat_map(|y: usize| (0..self.width).map(move |x| (x, y)));
        &i
    }
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/lib.rs:12:43
   |
12 |         let i = (0..self.height).flat_map(|y: usize| (0..self.width).map(move |x| (x, y)));
   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 11:13...
  --> src/lib.rs:11:13
   |
11 |     fn iter<'a>(&'a self) -> &'a impl Iterator<Item = (usize, usize)> {
   |             ^^
   = note: ...so that the types are compatible:
           expected &&Grid
              found &&'a Grid
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that return value is valid for the call
  --> src/lib.rs:11:34
   |
11 |     fn iter<'a>(&'a self) -> &'a impl Iterator<Item = (usize, usize)> {
   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我不知道如何将适当的生存期引用返回给迭代器。我了解迭代器的生命周期不得超过基础Grid结构的生命周期。

2 个答案:

答案 0 :(得分:3)

返回类型不能为引用。诀窍是为返回类型添加一个生存期说明符。另外,两个闭包都必须具有move才能捕获selfy的所有权。

fn iter<'a>(&'a self) -> impl Iterator<Item = (usize, usize)> + 'a {
    (0..self.height).flat_map(move |y| (0..self.width).map(move |x| (x, y)))
}

答案 1 :(得分:3)

这里没有理由维护对原始结构的任何引用,因为所有封闭值都实现了Copy。您只需要从该结构中提取heightwidth,然后进行复制:

fn iter(&self) -> impl Iterator<Item = (usize, usize)> {
    let Self { height, width } = *self;
    (0..height).flat_map(move |y| (0..width).map(move |x| (x, y)))
}