将特征生命周期变量绑定到 &self 生命周期

Tying a trait lifetime variable to &self 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 特征中显式生命周期变量的要点是允许 Foo 对象上 get_ref() 的 return 值比 [=13] =] 本身,将 return 值的生命周期与 Foo 缓冲区的生命周期联系起来。

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

Tying a trait lifetime variable to &self lifetime

不可能。

Is there any there any reason that this fundamentally cannot be done?

是的。拥有向量与借用的切片不同。您的特征 GetRef 仅对已经代表“贷款”且不拥有切片的事物有意义。对于像 Bar 这样的拥有类型,你不能安全地 return 一个比 Self 还长的借来的切片。这就是借用检查器为了避免悬挂指针而阻止的内容。

您尝试做的是link生命周期参数到Self的生命周期。但是 Self 的生命周期不是其 类型 的 属性。这仅取决于定义该值的范围。这就是为什么您的方法不起作用的原因。

另一种看待它的方式是:在特征中,您必须明确说明 Self 是否被方法及其结果借用。您将 GetRef 特征定义为 return 而非 link 为 Self w.r.t。一生。所以,不借。因此,它对于拥有数据的类型是不可实现的。您不能在不借用 Vec.

的情况下创建引用 Vec 元素的借用切片

If not, how can I do this?

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

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

这个trait的意思是get_ref Self和return是一种“借”,因为当前的生命周期省略规则。它相当于更明确的形式

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..] }
}

你可以为 &self 创造不同的生命周期,并产生这样的特质:

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();
    }
}