程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]?

开发过程中遇到如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]的问题如何解决?下面主要结合日常开发的经验,给出你关于如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]的解决方法建议,希望对你解决如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]有所启发或帮助;

我正在尝试为 &[u8] 数据构建一个临时包装类,允许调用者以其原始生命周期而不是临时包装生命周期提取数据。

如果直接使用 &[u8],这是有效的: Playground:

struct Wrapper1<'a> {
    data: &'a [u8],}

impl<'a> Wrapper1<'a> {
    // In the return value,we return lifetime 'a,not the lifetime of the wrapper
    pub fn get(&self) -> &'a [u8] {
        &self.data[2..]
    }
}

fn func(data: &[u8]) -> &[u8] {
    let wrapper = Wrapper1 { data };
    // Note that we can return wrapper.get() even though Wrapper1 goes out of scope
    wrapper.get()
}

fn main() {
    let data = vec![5; 10];
    println!("{:?}",func(&data));
}

现在我想在抽象可变性的同时做同样的事情,即我需要使用 &[u8]AsRef<[u8]>,而不是使用 AsMut<[u8]>。我尝试了以下方法,但不起作用。 Playground:

use std::marker::PhantomData;

struct Wrapper2<'a,S: 'a + AsRef<[u8]>> {
    data: S,_p: PhantomData<&'a S>,}

impl<'a,S: 'a + AsRef<[u8]>> Wrapper2<'a,S> {
    pub fn get<'b>(&'b self) -> &'a [u8] {
        &self.data.as_ref()[2..]
    }
}

fn func(data: &[u8]) -> &[u8] {
    let wrapper = Wrapper2 {
        data,_p: PhantomData,};
    wrapper.get()
}

fn main() {
    let data = vec![5; 10];
    println!("{:?}",func(&data));
}

错误信息:

error[E0495]: cAnnot infer an appropriate lifetime for autoref due to conflicTing requirements
  --> src/main.rs:10:20
   |
10 |         &self.data.as_ref()[2..]
   |                    ^^^^^^
   |
note: first,the lifetime cAnnot outlive the lifetime `'b` as defined on the method body at 9:16...
  --> src/main.rs:9:16
   |
9  |     pub fn get<'b>(&'b self) -> &'a [u8] {
   |                ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:10:10
   |
10 |         &self.data.as_ref()[2..]
   |          ^^^^^^^^^
note: but,the lifetime must be valID for the lifetime `'a` as defined on the impl at 8:6...
  --> src/main.rs:8:6
   |
8  | impl<'a,S> {
   |      ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:10:9
   |
10 |         &self.data.as_ref()[2..]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^

它无法为 Wrapper2::get() 的返回找到一个好的生命周期,因为它需要它比 &self 的生命周期更长。

有没有办法像我在上面的 wrapper 示例中所做的那样将它与 &[u8] 生命周期分离?

解决方法

经过一番挖掘,我现在更了解情况了。问题是 S: AsRef<[u8]> 不仅允许 S&[u8]&mut [u8] 之类的引用类型,还可以是 Vec<u8> 之类的对象。然对于引用,您可能会争辩说应该有一种方法可以将它们的生命周期延长到 Wrapper 生命周期之外,但对于 Vec<u8>,这显然没有意义,因为 Vec<u8> 会随着wrapper

我想出了两种可能的解决方案:

1.不要延长引用生命周期,而是允许一种方法来提取内部对象。

这允许问题中提出的 func 中的 return 语句。

Playground

struct Wrapper2<S: AsRef<[u8]>> {
    data: S,}

impl<S: AsRef<[u8]>> Wrapper2<S> {
    pub fn get(&self) -> &[u8] {
        &self.data.as_ref()[2..]
    }
    
    pub fn extract(self) -> S {
        // but note that we can only return the full data,// not a subset like get() or get_mut() would be doing
        self.data
    }
}

impl<S: AsRef<[u8]> + AsMut<[u8]>> Wrapper2<S> {
    pub fn get_mut(&mut self) -> &mut [u8] {
        &mut self.data.as_mut()[2..]
    }
}

fn func(data: &[u8]) -> &[u8] {
    let wrapper = Wrapper2 { data };
    let _g = wrapper.get();
    wrapper.extract()
}

fn func_mut(data: &mut [u8]) -> &mut [u8] {
    let mut wrapper = Wrapper2 { data };
    let _g = wrapper.get_mut();
    wrapper.extract()
}

fn main() {
    let mut data = vec![5; 10];
    println!("{:?}",func(&data));
    println!("{:?}",func_mut(&mut data));
}

2.将类型明确限制为 &[u8]&mut [u8]

这意味着我们不再使用 AsRefVec 不在图片中,我们知道我们实际上有一个引用。在这种情况下,生命周期扩展适用于 &[u8] 情况,即我们可以从包装器中获取 &[u8] 引用,并且该引用将在包装器中存活。对于 &mut [u8],不幸的是,我们仍然需要选项 1 中的 extract 函数。

这个解决方案仍然实现了作为引入 AsRef / AsMut 的原因所提到的“对可变性进行抽象”的目标,它只是在没有这些特征的情况下做到了。

Playground

struct Wrapper2<S> {
    data: S,}

impl <'a> Wrapper2<&'a [u8]> {
    fn get(&self) -> &'a [u8] {
        &self.data[2..]
    }
}

impl <'a> Wrapper2<&'a mut [u8]> {
    fn get_mut(&mut self) -> &mut [u8] {
        &mut self.data[2..]
    }
    
    fn extract(self) -> &'a mut [u8] {
        &mut self.data[2..]
    }
}

fn func(data: &[u8]) -> &[u8] {
    let wrapper = Wrapper2 { data };
    wrapper.get()
}

fn func_mut(data: &mut [u8]) -> &mut [u8] {
    let mut wrapper = Wrapper2 { data };
    let _a = wrapper.get_mut();
    let _b = wrapper.get_mut();
    wrapper.extract()
}

fn main() {
    let mut data = vec![5; 10];
    println!("{:?}",func_mut(&mut data));
}

大佬总结

以上是大佬教程为你收集整理的如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]全部内容,希望文章能够帮你解决如何将生命周期与 AsRef 包装器分离? 1.不要延长引用生命周期,而是允许一种方法来提取内部对象。2.将类型明确限制为 &[u8] 和 &mut [u8]所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。