【问题标题】:How do you create a generic function in Rust with a trait requiring a lifetime?如何在 Rust 中创建一个需要生命周期的泛型函数?
【发布时间】:2018-03-21 01:53:17
【问题描述】:

我正在尝试编写一个与数据库一起使用并表示可以存储的东西的特征。为此,该特征继承自其他特征,其中包括 serde::Deserialize 特征。

trait Storable<'de>: Serialize + Deserialize<'de> {
    fn global_id() -> &'static [u8];
    fn instance_id(&self) -> Vec<u8>;
}

struct Example {
    a: u8,
    b: u8
}

impl<'de> Storable<'de> for Example {
    fn global_id() -> &'static [u8] { b"p" }
    fn instance_id(&self) -> Vec<u8> { vec![self.a, self.b] }
}

接下来,我正在尝试使用通用函数编写此数据:

pub fn put<'de, S: Storable>(&mut self, obj: &'de S) -> Result<(), String> {
    ...
    let value = bincode::serialize(obj, bincode::Infinite);
    ...
    db.put(key, value).map_err(|e| e.to_string())
}

但是,我收到以下错误:

error[E0106]: missing lifetime specifier
--> src/database.rs:180:24
    |
180 |     pub fn put<'de, S: Storable>(&mut self, obj: &'de S) -> Result<(), String> {
    |                        ^^^^^^^^ expected lifetime parameter

Minimal example on the playground.

我将如何解决这个问题,可能完全避免它?

【问题讨论】:

    标签: rust traits lifetime


    【解决方案1】:

    您的 'de 生命周期在错误的位置 - 您需要它来指定 Storable 的参数,而不是引用 obj 的生命周期。

    代替

    fn to_json<'de, S: Storable>(obj: &'de S) -> String {
    

    使用

    fn to_json<'de, S: Storable<'de>>(obj: &S) -> String {
    

    Playground.

    obj 的生命周期在这里实际上并不重要,因为您没有返回任何派生自它的值。您只需要证明S 实现了Storable&lt;'de&gt; 在某个生命周期内'de

    如果你想完全消除'de,你应该使用DeserializeOwned,正如the other answer所描述的那样。

    【讨论】:

      【解决方案2】:

      您已经使用泛型参数定义了Storable,在本例中为生命周期。这意味着泛型参数必须在整个应用程序中传播:

      fn put<'de, S: Storable<'de>>(obj: &'de S) -> Result<(), String> { /* ... */ }
      

      您还可以决定使通用具体化。这可以通过具体的类型或生命周期(例如'static)来完成,或者将其放在特征对象后面。

      Serde 也有 a comprehensive page about deserializer lifetimes。它提到您也可以选择使用DeserializeOwned

      trait Storable: Serialize + DeserializeOwned { /* ... */ }
      

      您也可以对自己的 trait 使用与 DeserializeOwned 相同的概念:

      trait StorableOwned: for<'de> Storable<'de> { }
      
      fn put<'de, S: StorableOwned>(obj: &'de S) -> Result<(), String> {
      

      【讨论】:

        猜你喜欢
        • 2014-11-16
        • 1970-01-01
        • 2015-10-15
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2013-07-03
        • 2019-12-27
        相关资源
        最近更新 更多