闭包内部容器对象的生命周期推断

3

我有一个例程,它会处理容器中的对象,并引用存储在另外两个容器中的这些对象。
然而,我没有找到Rust的解决方法,生命周期推断似乎禁止了这种操作,我不知道该如何解决。

fn main() {
    let mut deck : Deck = Deck::new();
    let mut p1 : Hand = Hand::new();
    let mut p2 : Hand = Hand::new();


    do_hands(|data: &[Card]| -> Result<(),()> {
      for card in data {
        deck.insert(card.id, CardCell::new(*card));

        let card: &CardCell = deck.get_mut(&card.id).unwrap();
        handle_hand(&mut card, &mut p1, &mut p2);

      }      
      return Ok(());
    });

}

这是完整的游乐场链接:https://play.rust-lang.org/?gist=6079ade83e3fcf06f35397eac2e82d05&version=nightly。它与 IT 技术有关。请注意,保留了 HTML 标签。
1个回答

2

我在 playground 中尝试了一下,并进行了以下更改,使代码编译:

  1. 更改 handle_hand 的签名

    初始签名为 fn handle_hand<'a>(_card: &'a mut CardCell, _p1: &mut Hand<'a>, _p2: &mut Hand<'a>),但这正是编译器错误的原因。该签名要求所有输入参数具有相同的生命周期,但在您的代码中并非如此。在闭包内部,card 的生命周期明显比 p1p2 更短。因此,修改后的签名简单地变为:fn handle_hand<'a, 'b>(_card: &'b mut CardCell, _p1: &mut Hand<'a>, _p2: &mut Hand<'a>)

  2. 更改闭包内部的 card 的签名。

    由于 handle_hand 需要一个 &mut CardCell,因此您必须将 card 声明为 let mut card: &mut CardCell =...

  3. 将复制特性导出到 Card 结构中。我将此放在最后,因为这取决于您如何进一步编写结构体。但是,在此时,它只是 u64 的包装器,您可以简单地在其上执行 #[derive(Clone, Copy]。这是必需的,因为您正在使用的 Cell 结构需要一个复制类型。导出适用于此处,因为您的所有结构字段都已实现了复制类型。

这是更新后的 playground


谢谢,我已经尝试过了,但是一旦这样做,它就会阻止我将CardCell引用存储到p1或p2中,请考虑这个:https://play.rust-lang.org/?gist=b1dc8cb220daca0efaa0e5a6b4501786&version=nightly - Arkaitz Jimenez
啊哈,我认为 _card 的引用不能像现在这样存储在 p1p2 中,因为 card 的生命周期比 p1/p2 更短,因为它是在闭包内创建的。换句话说,您可能需要在闭包外部创建 card,以便它具有与 p1/p2 相同的生命周期。 - bow
嗯,所以我可能需要改变代码的工作方式,我不能在外部创建卡片,因为我需要闭包的参数来创建卡片,然后将其存储在容器中,然后实际上可能会稍微更改一下,然后将其存储在p1或p2中。 - Arkaitz Jimenez
我确实这么认为。我更改了handle_card的签名,以便它可以在当前设置下工作:在闭包内创建卡片。但是,如果您确实打算推回到p1/p2,则必须以另一种方式创建卡片,以确保其引用的生命周期与p1/p2相同。 - bow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接