如何设置这些结构的生命周期?

How to set the lifetime on these structures?

我正在尝试制作一个迭代器,它从移动列表中过滤掉某些移动。为了不拥有返回的移动的所有权,它们被引用。但是,这样做时会出现 missing lifetime specifier 编译器错误。由于我有一个结构链,我认为解决问题的第一步是开始将生命周期放在 MoveFilter 上,然后放在 IntoIterator 中的 type Item 上。然而,它抱怨使用未声明的生命周期。 代码:

pub struct GameMove {
    pub from: usize,
    pub to: usize,
    pub move_type: GameMoveType,
    pub piece_type: PieceType,
}
#[derive(PartialEq, Clone, Debug)]
pub enum GameMoveType {
    Quiet,
    Capture(PieceType),
}

#[derive(PartialEq, Clone, Debug)]
pub enum PieceType {
    King,
    Pawn
}

pub fn match_move_type(move_type: &GameMoveType) -> usize {
    match move_type {
        GameMoveType::Quiet => 0,
        GameMoveType::Capture(_) => 1,
    }
}

pub struct MoveFilter<'a> {
    legal_moves: Vec<GameMove>,
    move_type: GameMoveType,
}

impl IntoIterator for MoveFilter {
    type Item = &'a GameMove;
    type IntoIter = MoveFilterIterator;
    fn into_iter(self) -> Self::IntoIter {
        MoveFilterIterator {
            legal_moves: self.legal_moves,
            move_type: match_move_type(&self.move_type),
            index: 0,
        }
    }
}

pub struct MoveFilterIterator {
    legal_moves: Vec<GameMove>,
    move_type: usize,
    index: usize,
}

impl Iterator for MoveFilterIterator {
    type Item = &GameMove;
    fn next(&mut self) -> Option<&GameMove> {
        while self.index < self.legal_moves.len() {
            if match_move_type(&self.legal_moves[self.index].move_type) == self.move_type {
                Some(&self.legal_moves[self.index])
            } else {
                self.index += 1;
            }
        }
        None
    }
}

您的 取得 MoveFilter 所有权的方法 fn into_iter(self: MoveFilter) 和 方法 fn next(&mut self) -> Option<&GameMove> 只想分发对 GameMove 的不可变引用。在您的 into_iter 获得 MoveFilter 的所有权并完全使用它之后,谁应该拥有引用的 GameMove

解决它的一种方法是为 &'a MoveFilter 实现 IntoIterator,它不会取得 MoveFilter 的所有权,因此不必担心所有 [=14] =]s 在有任何引用 &'a GameMove 浮动时被丢弃:

pub struct GameMove {
    pub from: usize,
    pub to: usize,
    pub move_type: GameMoveType,
    pub piece_type: PieceType,
}

#[derive(PartialEq, Clone, Debug)]
pub enum GameMoveType {
    Quiet,
    Capture(PieceType),
}

#[derive(PartialEq, Clone, Debug)]
pub enum PieceType {
    King,
    Pawn
}

pub fn match_move_type(move_type: &GameMoveType) -> usize {
    match move_type {
        GameMoveType::Quiet => 0,
        GameMoveType::Capture(_) => 1,
    }
}

pub struct MoveFilter {
    legal_moves: Vec<GameMove>,
    move_type: GameMoveType,
}

impl<'t> IntoIterator for &'t MoveFilter {
    type Item = &'t GameMove;
    type IntoIter = MoveFilterIterator<'t>;
    fn into_iter(self) -> Self::IntoIter {
        MoveFilterIterator {
            legal_moves: &self.legal_moves[..],
            move_type: match_move_type(&self.move_type),
            index: 0,
        }
    }
}

pub struct MoveFilterIterator<'a> {
    legal_moves: &'a [GameMove],
    move_type: usize,
    index: usize,
}

impl<'a> Iterator for MoveFilterIterator<'a> {
    type Item = &'a GameMove;
    fn next(&mut self) -> Option<&'a GameMove> {
        while self.index < self.legal_moves.len() {
            if match_move_type(&self.legal_moves[self.index].move_type) == self.move_type {
                return Some(&self.legal_moves[self.index])
            } else {
                self.index += 1;
            }
        }
        None
    }
}

另一种可能的解决方案是保持 IntoIterator for MoveFilter 不变,然后将 Item = &GameMove 更改为 Item = GameMove。这会给你一个破坏性的迭代器,它移动 MoveFilter 并且只能使用一次,但我认为这不是你从 type Item = &GameMove 开始时想要的。实现它似乎有点尴尬,因为从向量中删除单个元素并非完全微不足道,而且我不太明白 while-loop 在那里做什么。