模板类型参数仅针对特质绑定

发布于 2025-02-08 11:54:41 字数 392 浏览 1 评论 0原文

在Rust中,在结构范围中应使用对模板类型参数强迫使用参数的限制。

struct S1<'a, T> where T: Deserialize<'a>
{
    pub data: T
}
    
impl<'a, T> S1<'a, T> {
    fn update(&mut self, str_json: String) {
        self.data = serve_json::from_str(&str_json).unwrap();
    } 
}

在上述代码中,Serve_json需要使用Lifetime参数实现Deserialiser的类型,但是该结构并未将其直接用于底部成员。克服问题的最佳方法是什么?

In rust there is a constraint on template type parameters forcing to have usage of the parameter in each template argument should be used in the scope of structure.

struct S1<'a, T> where T: Deserialize<'a>
{
    pub data: T
}
    
impl<'a, T> S1<'a, T> {
    fn update(&mut self, str_json: String) {
        self.data = serve_json::from_str(&str_json).unwrap();
    } 
}

In the above mentioned code serve_json requires the type to implement deserialiser with lifetime parameter, but the structure doesn't directly use it for the underling members. what is the best way to overcome the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

︶ ̄淡然 2025-02-15 11:54:41

最简单的方法是在s1上不限制t,完全仅在实现上:

struct S1<T> {
    pub data: T
}
    
impl<'a, T> S1<T> where T: Deserialize<'a> {
    // ...
}

<

  • a href =“ https://stackoverflow.com/a/ 66369912/501250“>特征边界是否应该在结构和inmend?中重复

The simplest way is to not bound T on S1 at all, only on the implementation:

struct S1<T> {
    pub data: T
}
    
impl<'a, T> S1<T> where T: Deserialize<'a> {
    // ...
}

Further reading:

尴尬癌患者 2025-02-15 11:54:41

我考虑 @cdhowie 的答案,并尝试使示例完全工作。
为此,我们必须确保传入字符串的寿命(str_json)与deSerialize&lt;'a&gt;的寿命兼容。

使用String参数,情况并非如此:当功能结束时,它将消失。
然后,我们需要一个&amp; str,并明确将其寿命与delelialize&lt;'a&gt;之一相关联。

此页面很好地解释了为什么deSerialize&lt;重要的是:它可以启用零拷贝提取(合适的时)。

为了说明这一点,下面的示例首先处理一个拥有其数据的结构(a string),然后处理第二个引用其数据的结构(a &amp; str )。

根据同一页面deserializeded在我们无法保证时要考虑要解析的传入字符串将比提取的数据更长。
在这种情况下,我们可以回到参数为String的情况。

use serde::{de::DeserializeOwned, Deserialize};

#[derive(Debug)]
struct S1<T> {
    pub data: T,
}

impl<'a, T> S1<T>
where
    T: Deserialize<'a>,
{
    fn update_from_str(
        &mut self,
        str_json: &'a str,
    ) {
        self.data = serde_json::from_str(str_json).unwrap();
    }
}

impl<T> S1<T>
where
    T: DeserializeOwned,
{
    fn update_from_string(
        &mut self,
        str_json: String,
    ) {
        self.data = serde_json::from_str(&str_json).unwrap();
    }
}

fn main() {
    let mut owned = S1 {
        data: "one".to_owned(),
    };
    println!("owned before {:?}", owned);
    owned.update_from_str(" \"two\" ");
    println!("owned after {:?}", owned);
    //
    let mut referenced = S1 { data: "three" };
    println!("referenced before {:?}", referenced);
    referenced.update_from_str(" \"four\" ");
    println!("referenced after {:?}", referenced);
    //
    let mut owned_and_string = S1 {
        data: "five".to_owned(),
    };
    println!("owned_and_string before {:?}", owned_and_string);
    owned_and_string.update_from_string(" \"six\" ".to_owned());
    println!("owned_and_string after {:?}", owned_and_string);
}
/*
owned before S1 { data: "one" }
owned after S1 { data: "two" }
referenced before S1 { data: "three" }
referenced after S1 { data: "four" }
owned_and_string before S1 { data: "five" }
owned_and_string after S1 { data: "six" }
*/

I take into consideration the answer of @cdhowie and try to make the example work entirely.
To do so, we have to ensure the lifetime of the incoming string (str_json) is compatible with the lifetime of Deserialize<'a>.

With a String parameter, it is not the case: it will disappear when the function ends.
Then, we need a &str and explicitly associate its lifetime with the one of Deserialize<'a>.

This page explains quite well why the lifetime on Deserialize<'a> is important: it enables zero-copy extractions (when suitable).

In order to illustrate this, the example below first deals with a struct which owns its data (a String) and then a second struct which references its data (a &str).

According to the same page, DeserializedOwned is to be considered when we cannot guaranty that the incoming string to be parsed will live longer than the extracted data.
In this case, we can get back to the situation where the parameter is a String.

use serde::{de::DeserializeOwned, Deserialize};

#[derive(Debug)]
struct S1<T> {
    pub data: T,
}

impl<'a, T> S1<T>
where
    T: Deserialize<'a>,
{
    fn update_from_str(
        &mut self,
        str_json: &'a str,
    ) {
        self.data = serde_json::from_str(str_json).unwrap();
    }
}

impl<T> S1<T>
where
    T: DeserializeOwned,
{
    fn update_from_string(
        &mut self,
        str_json: String,
    ) {
        self.data = serde_json::from_str(&str_json).unwrap();
    }
}

fn main() {
    let mut owned = S1 {
        data: "one".to_owned(),
    };
    println!("owned before {:?}", owned);
    owned.update_from_str(" \"two\" ");
    println!("owned after {:?}", owned);
    //
    let mut referenced = S1 { data: "three" };
    println!("referenced before {:?}", referenced);
    referenced.update_from_str(" \"four\" ");
    println!("referenced after {:?}", referenced);
    //
    let mut owned_and_string = S1 {
        data: "five".to_owned(),
    };
    println!("owned_and_string before {:?}", owned_and_string);
    owned_and_string.update_from_string(" \"six\" ".to_owned());
    println!("owned_and_string after {:?}", owned_and_string);
}
/*
owned before S1 { data: "one" }
owned after S1 { data: "two" }
referenced before S1 { data: "three" }
referenced after S1 { data: "four" }
owned_and_string before S1 { data: "five" }
owned_and_string after S1 { data: "six" }
*/
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文