没有参考资料,我如何才能拥有终身依赖? [英] How can I have a lifetime dependency without a reference?
问题描述
我正在包装一个具有context
和device
对象的C库.由于device
保留对context
的内部引用,因此context
对象需要比device
对象更长.
I'm wrapping a C library that has context
and device
objects. The context
object needs to outlive the device
object because the device
keeps an internal reference to the context
.
为此,我在Device
包装器中使用了PhantomData
字段:
To express this, I use a PhantomData
field in the Device
wrapper:
use std::marker::PhantomData;
struct Context;
impl Context {
fn open_device<'a>(&'a self) -> Device<'a> {
Device { _context: PhantomData, }
}
}
struct Device<'a> {
_context: PhantomData<&'a Context>,
}
现在,在我的客户代码中,我想拥有一个既包含Context
又Device
对象的结构.但是由于Device
拥有对Context
的引用(伪造的),所以我无法做到这一点(请参阅
Now, in my client code, I would like to have a struct that holds both the Context
and Device
objects. But because the Device
holds a reference (a fake one) to the Context
, I'm not able to do this (see this question). But this is an unnecessary restriction because the Device
struct doesn't actually contain a reference to the Context
.
那么如何将Device
的生存期与Context
的生存期联系起来,以允许我将它们都保存在结构中?
So how can I tie the lifetime of the Device
to the lifetime of the Context
in a way that would allow me to hold both of them in a struct?
推荐答案
到目前为止,Rust无法表达引用同一结构中定义的对象的生存期,因此无法为该对象声明适当的生存期. Device
成员.
As of today, Rust is not able to express a lifetime that refers to an object defined in the same struct, so it's impossible to declare the proper lifetime for the Device
member.
除了将两个对象都直接存储在结构中之外,您还可以存储对这些结构的引用吗? (如果您要创建一个返回该结构的函数,则将无法使用.)
Instead of storing both objects directly in the struct, could you instead store references to these structs? (This won't work if you want to make a function that returns that struct.)
struct Both<'a: 'b, 'b> {
context: &'a Context,
device: &'b Device<'a>,
}
另一种选择是将Device
声明为具有Context
且具有'static
的生存期(我正在使用'static
,因为它是唯一具有名称的生存期),但始终使用一种方法来铸造"将Device
合并为具有适当生存期参数的参数,而不是直接使用该字段.
Another option is to declare the Device
as having a Context
with 'static
lifetime (I'm using 'static
because it's the only lifetime with a name), but always using a method to "cast" the Device
into one with appropriate lifetime parameters, rather than using the field directly.
struct Both {
context: Context,
device: Device<'static>,
}
impl Both {
fn get_device<'a>(&'a self) -> &'a Device<'a> {
&self.device
}
}
实际上,由于使用了生存期删除功能,因此不必在get_device
上显式指定生存期参数(顺便说一下,对于您的open_device
方法也是如此):
Actually, thanks to lifetime elision, it is not necessary to specify the lifetime parameters explicitly on get_device
(likewise for your open_device
method, by the way):
impl Both {
fn get_device(&self) -> &Device {
&self.device
}
}
只有一个陷阱:初始化结构时,您需要使用transmute
来了解设备的生命周期参数.
There's just a gotcha: you need to use transmute
to lie about the device's lifetime parameter when you initialize the struct.
use std::mem;
fn get_both() -> Both {
let context = Context; // could also be a parameter
let device: Device<'static> = unsafe { mem::transmute(context.open_device()) };
Both {
context: context,
device: device,
}
}
您可能还想考虑让Both
结构包含一个没有生命周期参数的Device
,然后将其包装在另一个具有生命周期参数的结构中,并从方法中返回它.
You might also want to consider having the Both
struct containing a Device
that has no lifetime parameter, then wrapping that in another struct that does have a lifetime parameter and returning that from a method.
use std::marker::PhantomData;
use std::mem;
struct Context;
impl Context {
fn open_device(&self) -> Device {
Device
}
}
struct Device;
struct DeviceWrapper<'a> {
_context: PhantomData<&'a Context>,
device: &'a Device,
}
struct Both {
context: Context,
device: Device,
}
impl Both {
fn get_device(&self) -> DeviceWrapper {
DeviceWrapper { _context: PhantomData, device: &self.device }
}
}
fn get_both() -> Both {
let context = Context;
let device = context.open_device();
Both {
context: context,
device: device,
}
}
(实际上,DeviceWrapper
可能不需要_context
成员,因为DeviceWrapper
的生存期已经与Both
的生存期绑定了.)
(In fact, the DeviceWrapper
probably doesn't need the _context
member, since the DeviceWrapper
's lifetime is tied to that of the Both
already.)
这篇关于没有参考资料,我如何才能拥有终身依赖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!