Как я могу вернуть соответствующую итерированную ссылку на итератор над содержимым структуры? - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь реализовать итератор для двумерной сетки, как показано ниже (это упрощение немного более сложной настройки):

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 голосов
/ 06 декабря 2018

Нет причин поддерживать какие-либо ссылки на исходную структуру здесь, поскольку все закрытые значения реализуют Copy.Вам просто нужно извлечь height и width из структуры, сделав копию, как вы это делаете:

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)))
}
0 голосов
/ 06 декабря 2018

Тип возвращаемого значения не должен быть ссылкой.Хитрость заключается в том, чтобы добавить указатель времени жизни для возвращаемого типа.Кроме того, оба закрытия должны иметь move для захвата владения self и y.

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)))
}
...