将特征生命周期变量绑定到 &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();
}
}
我想按照以下思路做一些事情:
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();
}
}