我正在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/