[英]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_struct
在Obj<'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),因此避免使用生命周期並使用Box
, Rc
等更加容易。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.