我正在Rust中编写一个简单的游戏,其中包括一个Drawer,该代码会被构建一次,然后通过多种方法作为可变引用进行传递:

pub struct Drawer<'a> {
    // ...
    renderer: Renderer<'a>,
    // ...
}

fn pause(drawer: &mut Drawer, events: &[Event]) {
    // ...
    drawer.draw_text(&TextPos::Centered, "Paused", 1);
    // ...
}

我想重构代码以引入一个流畅的界面来绘制文本,例如:
drawer.text()
    .size(4)
    .centered()
    .draw("Paused");

我通过创建一个TextDrawer结构来做到这一点,该结构包含对Drawer的引用:
pub struct TextDrawer<'a, 'b: 'a> {
    pos: TextPos,
    size: u32,
    drawer: &'a mut Drawer<'b>,
}

impl<'a> Drawer<'a> {
     pub fn text(&mut self) -> TextDrawer {
        TextDrawer {
            pos: TextPos::At(0, 0),
            size: 1,
            drawer: self,
        }
    }
}

我认为我在结构上放置的生命周期是正确的(引用必须持续到Drawer本身,只要它持续时间)。

但是,在添加显式生存期之前,我的text方法将无法编译。当我这样做时,每个调用text的方法都需要显式的生存期,依此类推。我很惊讶必须指出这些生命周期:毕竟,它们都是fn foo<'a, 'b: 'a>(drawer: &mut'a Drawer<'b>)的形式。在此之前,我已经假设这已经是推断的生命周期,因为引用始终必须与Drawer本身一样长。

我是否有必要将这些显式生命期放在所有其他方法签名上?还是可以通过其他方式避免这种情况?

最佳答案

多亏了上述Lukas制作的minimal example,我才意识到我已经简单地将生存期参数倒向了text方法。

我不正确的一生:

impl<'a> Drawer<'a> {
    pub fn text<'b>(&'b mut self) -> TextDrawer<'a, 'b> {
        // omitted
    }
}

正确的生命周期:
impl<'a> Drawer<'a> {
    pub fn text<'b>(&'b mut self) -> TextDrawer<'b, 'a> {
        // omitted
    }
}

此后,一切都将编译而没有任何进一步的显式生存期。

关于rust - 使用包含借用参数的结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43150295/

10-12 14:56