簡體   English   中英

如何為具有生命周期的結構實現“具有靜態生命周期的特征”?

[英]How to implement a trait with 'static lifetime for a struct with lifetime 'a?

我有一個trait Surface: 'static我想為struct Obj<'a> 該特征必須是'static因為我想將Surface類型的對象存儲在Vec<Box<Surface>>

在第一步中,我嘗試了這一點。

impl<'a> Surface for Obj<'a> {}

由於'static'a的生命周期不匹配,因此無法'a 換句話說: Surface生存期可能比Obj長,因為Surface'static 我對實現進行了如下更改。

impl<'a> Surface for Obj<'a> where 'a: 'static {}

據我正確地理解文檔,我正在做的是, 'a可以超越'static 我要這個嗎?

如果我轉讓Obj<'a>的所有權,則編譯器會告訴我, Obj內部的可變引用壽命不會足夠長,並且仍會被借用。

這是一個簡短的例子。

trait Surface: 'static {}

struct Manager {
    storage: Vec<Box<Surface>>,
}

impl Manager {
    fn add(&mut self, surface: impl Surface) {
        self.storage.push(Box::new(surface));
    }
}

struct SomeOtherStruct {}

struct Obj<'a> {
    data: &'a mut SomeOtherStruct,
}

impl<'a> Obj<'a> {
    fn new(some_struct: &'a mut SomeOtherStruct) -> Self {
        Obj { data: some_struct }
    }
}

impl<'a> Surface for Obj<'a> where 'a: 'static {}

fn main() {
    let mut some_struct = SomeOtherStruct {};
    let mut manager = Manager {
        storage: Vec::new(),
    };

    let obj = Obj::new(&mut some_struct);
    manager.add(obj);
}

游樂場

error[E0597]: `some_struct` does not live long enough
  --> src/main.rs:33:24
   |
33 |     let obj = Obj::new(&mut some_struct);
   |               ---------^^^^^^^^^^^^^^^^-
   |               |        |
   |               |        borrowed value does not live long enough
   |               argument requires that `some_struct` is borrowed for `'static`
34 |     manager.add(obj);
35 | }
   | - `some_struct` dropped here while still borrowed

換句話說, &mut some_struct是生命周期'a但需要'static 好的,很明顯,因為some_structObj<'a>所以它不能是'static

這是我想要做的“ Rust like”嗎? 我不知道如何使它工作。 它的確與生命周期混淆。 我想我可以使用Rc<T>解決這個問題,但這會使事情變得更復雜。

首先要注意的是:

impl<'a> Surface for Obj<'a> where 'a: 'static {}

冗長

impl Surface for Obj<'static> {}

您已正確識別問題:

換句話說, &mut some_struct是生命周期'a但需要'static

您需要將some_struct聲明為static

fn main() {
    static mut SOME_STRUCT: SomeOtherStruct = SomeOtherStruct {};
    // ...
    let obj = unsafe { Obj::new(&mut SOME_STRUCT) };
    //  ...
}

問題是,您不能安全地訪問可變靜態變量,因為它們可以同時在多個線程中進行變異,這是一個問題,因此您需要unsafe

所以不,您的代碼不是“ Rust like”,但恐怕您無法使用當前的體系結構進行更改。


該特征必須是“靜態的”,因為我想將Surface類型的對象存儲在Vec<Box<Surface>>

我不明白為什么您首先認為需要'static的,例如此代碼完全合法:

trait Foo {}
struct Bar;

impl Foo for Bar {}

fn main() {
    let b: Box<Foo> = Box::new(Bar);
}

如何實現具有'static壽命為a的結構'static壽命'a

你沒有,也不能。 'static生命期'static的目的是說“在程序的整個持續時間內都存在的東西”。 除了 'static本身,沒有任何生存期'a滿足此要求。

@hellow的答案有效並解決了我的問題,但是感覺很hacky,並且對Rust有用。

有了您的提示,我找到了一個更好的解決方案,該解決方案也可以工作並且不使用unsafe

解決方案1

我為Manager和類型Box<Surface + 'a>指定了明確的生命周期參數:

trait Surface {}

struct Manager<'a> {
    storage: Vec<Box<Surface + 'a>>,
}

impl<'a> Manager<'a> {
    fn add(&mut self, surface: impl Surface + 'a) {
        self.storage.push(Box::new(surface));
    }
}

struct SomeOtherStruct {}

struct Obj<'a> {
    data: &'a mut SomeOtherStruct,
}

impl<'a> Obj<'a> {
    fn new(some_struct: &'a mut SomeOtherStruct) -> Self {
        Obj {
            data: some_struct
        }
    }
}

impl<'a> Surface for Obj<'a> {}

fn main() {
    let mut some_struct = SomeOtherStruct{};
    let mut manager = Manager { storage: Vec::new() };

    let obj = Obj::new(&mut some_struct);
    manager.add(obj);
}

游樂場

解決方案2

Obj存儲Box<SomeOtherStruct>而不是&mut SomeOtherStruct 這將消除生命周期:

trait Surface {}

struct Manager {
    storage: Vec<Box<Surface>>,
}

impl Manager {
    fn add(&mut self, surface: impl Surface + 'static) {
        self.storage.push(Box::new(surface));
    }
}

struct SomeOtherStruct {}

struct Obj {
    data: Box<SomeOtherStruct>,
}

impl Obj {
    fn new(some_struct: Box<SomeOtherStruct>) -> Self {
        Obj {
            data: some_struct
        }
    }
}

impl Surface for Obj {}

fn main() {
    let some_struct = SomeOtherStruct{};
    let mut manager = Manager { storage: Vec::new() };

    let obj = Obj::new(Box::new(some_struct));
    manager.add(obj);
}

游樂場

我認為兩種解決方案都是好的。 我不知道哪種解決方案更好,並且我對這種解決方案的優缺點也沒有經驗。 對我來說(也許是因為我是一個初學者,並且仍然傾向於Rust),因此避免使用生命周期並使用BoxRc等更加容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM