如何为具有生命周期'a的结构实现具有'静态生命周期的特征?
Posted
技术标签:
【中文标题】如何为具有生命周期\'a的结构实现具有\'静态生命周期的特征?【英文标题】:How to implement a trait with 'static lifetime for a struct with lifetime 'a?如何为具有生命周期'a的结构实现具有'静态生命周期的特征? 【发布时间】:2019-08-05 00:32:03 【问题描述】:我有一个trait Surface: 'static
,我想为struct Obj<'a>
实现它。该特征需要为'static
,因为我想将Surface
类型的对象存储在Vec<Box<Surface>>
中。
在第一步中我尝试了这个。
impl<'a> Surface for Obj<'a>
由于'static
和'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);
(Playground)
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>
来解决这个问题,但这会使事情变得更复杂。
【问题讨论】:
【参考方案1】:如何为生命周期为
'a
的结构实现一个生命周期为'static
的特征?
你没有也不能。 'static
生命周期的目的是说“在整个程序期间都存在的东西”。没有任意生命周期 'a
满足此要求除了 'static
本身。
【讨论】:
【参考方案2】:第一件事:
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 一样”,但恐怕你不能用你当前的架构来改变它。
特征需要是“静态的”,因为我想将
Surface
类型的对象存储在Vec<Box<Surface>>
中。
我不明白你为什么认为你首先需要'static
,例如这段代码是完全合法的:
trait Foo
struct Bar;
impl Foo for Bar
fn main()
let b: Box<Foo> = Box::new(Bar);
【讨论】:
好的...首先感谢您的回答。那不是我想要的。我想要“生锈的方式”。你能告诉我生锈的方法吗,或者给我一个提示,我可以单独弄清楚。我做了我的特征'static
,因为这个签名fn add(&mut self, surface: impl Surface)
上的编译器错误没有'static
,编译器会抛出一个错误,但感谢提示我将其更改如下:fn add(&mut self, surface: impl Surface + 'static)
。现在我可以从特征中删除 'static。但问题仍然存在。如果我必须重构我的架构,以 rust 的方式归档,没问题,我正在学习。【参考方案3】:
@hellow's answer 工作并解决了我的问题,但感觉很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);
(Playground)
解决方案 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);
(Playground)
在我看来,这两种解决方案都很好。我不知道哪种解决方案更好,而且我对这种解决方案的优缺点没有经验。
对我来说(可能是因为我是初学者并且仍然倾向于 Rust)避免生命周期并使用 Box
、Rc
等更容易。
【讨论】:
以上是关于如何为具有生命周期'a的结构实现具有'静态生命周期的特征?的主要内容,如果未能解决你的问题,请参考以下文章
具有持久 HTTP 连接的 IDbConnection 生命周期管理