如何设置这些结构的寿命?

时间:2019-01-26 20:23:13

标签: rust lifetime

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

IntoIterator

1 个答案:

答案 0 :(得分:2)

您的之间存在差异 拥有fn into_iter(self: MoveFilter)所有权的方法MoveFilter 和 方法fn next(&mut self) -> Option<&GameMove>只希望分发对GameMove的不可变引用。在您的GameMove拥有into_iter的所有权并完全消耗掉之后,谁应该拥有引用的MoveFilter

解决此问题的一种方法是为IntoIterator实现&'a MoveFilter,因为它不需要拥有MoveFilter的所有权,因此不必担心所有GameMove当周围有任何引用&'a GameMove时,s被丢弃:

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循环在那里所做的事情。