将特质生命周期变量与自我生命联系起来

时间:2015-02-21 00:01:18

标签: rust lifetime

我想按照以下几点做点什么:

trait GetRef<'a> {
    fn get_ref(&self) -> &'a [u8];
}

struct Foo<'a> {
    buf: &'a [u8]
}

impl <'a> GetRef<'a> for Foo<'a> {
    fn get_ref(&self) -> &'a [u8] {
        &self.buf[1..]
    }
}

struct Bar {
    buf: Vec<u8>
}

// this is the part I'm struggling with:
impl <'a> GetRef<'a> for Bar {
    fn get_ref(&'a self) -> &'a [u8] {
        &self.buf[1..]
}

GetRef特征中显式生命周期变量的要点是允许get_ref()对象上的Foo的返回值比Foo本身更长,将将值的生命周期返回到Foo缓冲区的生命周期。

但是,我还没有找到以编译器接受的方式为GetRef实现Bar的方法。我已尝试过上述几种变体,但似乎无法找到有效的变体。有没有任何理由从根本上无法做到这一点?如果没有,我该怎么做?

2 个答案:

答案 0 :(得分:4)

  

将特质生命周期变量绑定到&amp; self lifetime

不可能。

  

有没有任何理由从根本上无法做到这一点?

是。拥有的向量与借用的切片不同。您的特征GetRef仅对已经代表“贷款”并且不拥有切片的事物有意义。对于像Bar这样的拥有类型,您无法安全地返回比Self更长的借用切片。这就是借用检查器阻止避免悬挂指针的原因。

您尝试将life参数链接到Self的生命周期。但Self的生命周期不是其类型的属性。它只取决于定义此值的范围。这就是为什么您的方法无法工作的原因。

另一种看待它的方法是:在一个特征中,你必须明确Self是否被方法借用及其结果。您定义了GetRef特征,以返回链接到Self w.r.t的内容。寿命。所以,没有借款。因此,对于拥有数据的类型,它是不可实现的。如果不借用Vec,则无法创建引用Vec元素的借用切片。

  

如果没有,我该怎么做?

取决于“this”到底是什么意思。如果你想写一个可以为借用的拥有的切片实现的“公分母”特征,你必须这样做:

trait GetRef {
    fn get_ref(&self) -> &[u8];
}

这个特性的含义是get_ref 借用 Self并返回一种“贷款”,因为当前的终身省略规则。它等同于更明确的形式

trait GetRef {
    fn get_ref<'s>(&self) -> &'s [u8];
}

现在可以对两种类型实施:

impl<'a> GetRef for Foo<'a> {
    fn get_ref(&self) -> &[u8] { &self.buf[1..] }
}

impl GetRef for Bar {
    fn get_ref(&self) -> &[u8] { &self.buf[1..] }
}

答案 1 :(得分:0)

你可以为自己创造不同的生命周期并导致你的特质:

trait GetRef<'a, 'b> {
    fn get_ref(&'b self) -> &'a [u8];
}

struct Foo<'a> {
    buf: &'a [u8]
}

impl <'a, 'b> GetRef<'a, 'b> for Foo<'a> {
    fn get_ref(&'b self) -> &'a [u8] {
        &self.buf[1..]
    }
}

struct Bar {
    buf: Vec<u8>
}

// Bar, however, cannot contain anything that outlives itself
impl<'a> GetRef<'a, 'a> for Bar {
    fn get_ref(&'a self) -> &'a [u8] {
        &self.buf[1..]
    }
}


fn main() {
    let a = vec!(1 as u8, 2, 3);
    let b = a.clone();
    let tmp;
    {
        let x = Foo{buf: &a};
        tmp = x.get_ref();
    }
    {
        let y = Bar{buf: b};
        // Bar's buf cannot outlive Bar
        // tmp = y.get_ref();
    }
}