我怎么能有没有参考一辈子依赖?(How can I have a lifetime dependen

2019-11-04 02:27发布

我包装,有一个C库contextdevice对象。 所述context对象需要活得比的device ,因为该对象device保持一个内部参考context

为了表达这一点,我使用的是PhantomData场的Device包装:

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>,
}

现在,在我的客户端代码,我想有一个同时拥有了一个struct ContextDevice对象。 但由于Device拥有一个引用(假的)的Context ,我不能做到这一点(见这个问题)。 但是,这是一个不必要的限制,因为该Device结构实际上并不包含对一个参考Context

那么,怎样才能将我的寿命扎Device的寿命Context的方式,可以让我在一个结构持有他们两个?

Answer 1:

截至今天,锈不能够表达一生是指在同一个结构定义的对象,所以不可能宣布参加适当的寿命Device成员。

而不是直接在结构存储这两个对象,你可以存储,而不是对这些结构引用? (如果你想返回的是结构的函数这是行不通的。)

struct Both<'a: 'b, 'b> {
    context: &'a Context,
    device: &'b Device<'a>,
}

另一种选择是声明Device为具有Context'static寿命(我用'static ,因为它是一个名称的唯一寿命),但总是用一种方法来‘投’的Device变成一个与适当的寿命参数,而不是直接使用领域。

struct Both {
    context: Context,
    device: Device<'static>,
}

impl Both {
    fn get_device<'a>(&'a self) -> &'a Device<'a> {
        &self.device
    }
}

事实上,由于寿命省音,没有必要明确指定的寿命参数get_device (同样为您open_device方法,顺便说一句):

impl Both {
    fn get_device(&self) -> &Device {
        &self.device
    }
}

这里只是一个疑难杂症:你需要使用transmute撒谎设备的生命周期参数在初始化的结构。

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不具有寿命参数,然后包裹在另一个结构确实有一辈子的参数和返回从一个方法。

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了。)



文章来源: How can I have a lifetime dependency without a reference?
标签: rust lifetime