传递基础引用字段的生命周期?

6
我正在尝试创建两个结构体来操作底层数据集;一个提供不可变的“读”操作,另一个允许修改。为了使其工作,我需要能够在修改对象中使用读取函数-因此,在修改函数中创建一个临时的新读取对象,以便查看底层数据。
以下是一些代码:
struct Read<'db> {
    x: &'db i32
}

impl<'db> Read<'db> {
    pub fn get(&'db self) -> &'db i32 { self.x }
}

struct Write<'db> {
    x: &'db mut i32
}

impl<'db> Write<'db> {
    fn new(x: &mut i32) -> Write { Write{x: x} }

    fn as_read(&'db self) -> Read<'db> {
        Read{x: self.x}
    }

    pub fn get(&'db self) -> &'db i32 { self.as_read().get() }
}    


fn main() {
    let mut x = 69i32;
    let y = Write::new(&mut x);
    println!("{}", y.get());
}

它无法编译 - 尽管我尽了最大的努力,但似乎从 Read::get 返回的引用生命周期绑定到了 Write::get 的作用域,而不是 Write'db 生命周期。我该如何使其编译?(并且,我想做的事情可行吗?这是最简单/最简洁的方法吗?)

1个回答

4
编译器试图表达的意思是,&'db self实际上意味着self: &'db Write<'db>。这意味着您将引用和类型绑定到相同的生命周期。在您的情况下,您实际上需要self: &'a Write<'db>,其中'a仅存在于as_read函数中。为了能够从'a引用返回'db引用,您需要通过约束'a: 'db来指定'a至少与'db生命周期一样长。
fn as_read<'a: 'db>(self: &'a Write<'db>) -> Read<'db> {
    Read{x: self.x}
}

pub fn get<'a: 'db>(self: &'a Write<'db>) -> &'db i32 { self.as_read().get() }

更简洁地说
fn as_read<'a: 'db>(&'a self) -> Read<'db> {
    Read{x: self.x}
}

pub fn get<'a: 'db>(&'a self) -> &'db i32 { self.as_read().get() }

Try it out in the Playground


奇怪的是,如果结构体不存储&mut,那么根本就不需要'a。这似乎有点奇怪。 - Shepmaster
完全不是这样。如果您可以多次调用as_read(),则最终会得到两个对i32的&mut引用。您可以看到,如果在as_read中将其重新借用为不可变,则可以使用@Wavin的代码:http://is.gd/Nt66hL 这可能是更好的答案。我会更新我的代码。 - oli_obk
嗯,好的,我不知道发生了什么。可能已经有人提出了这个问题……但我现在找不到它。 - oli_obk
啊,你的版本能够工作是因为你有 &'db self。虽然我理解这样做的原理,但我认为只有 &self 也应该可以工作。生命周期省略会为 self 插入一个 'a,但这并不重要,因为我们正在复制内部引用及其生命周期。也许复制不起作用是因为有 mut - Shepmaster
&mut 总是被重新借用或移动,但无法复制。我猜 rustc 无法理解 'a:'db,尽管这在这里应该很明显。 - oli_obk
显示剩余2条评论

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