使用生命周期参数声明特征对象的向量

时间:2016-09-09 23:29:30

标签: rust lifetime

我对上下文类型进行了Widget特征参数化:

trait Widget<C> {
    fn f<'a>(&self, ctx: &'a mut C);
}

某些小部件的上下文类型相同,但包含引用,因此参数化:

struct Ctxt<'c> {
    data: &'c u32,
}

struct W1 {}
struct W2 {}

impl<'c> Widget<Ctxt<'c>> for W1 { // and W2
    fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
        unimplemented!()
    }
}

我有一个多小部件想要存储其中的几个:

struct WV {
    widgets: Vec<Box<Widget<Ctxt<????>>>>,
}

impl<'c> Widget<Ctxt<'c>> for WV {
    fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
        for w in &self.widgets {
            w.f(ctx);
        }
    }
}

看起来我需要Vec<Box<Widget<for<'c> Ctxt<'c>>>>;但你做不到!或者,仅在f的定义中指定生命周期:

impl Widget<Ctxt> for W {
    fn f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
        unimplemented!()
    }
}

这也不起作用(Ctxt的缺少生命周期参数)。

上下文的目的是将一个可变引用传递给长期存在的东西,这只在f期间需要; &mut引用无法存储在W1等中。我真的不想为Ctxt指定任何生命周期。

如何存储特征的多个实现者,这些实现者允许传入包含引用的上下文?

1 个答案:

答案 0 :(得分:3)

经过一夜的睡眠,我觉得我有一个答案。我可以通过新的特征CtxtCtxtWidget间接选择新的特征来推迟选择impl<'c> Widget<Ctxt<'c>>生命周期:

trait Widget<C> {
    fn f<'a>(&self, ctx: &'a mut C);
}

struct W1 {}
struct W2 {}
struct Ctxt<'c> {
    data: &'c u32,
}

trait CtxtWidget {
    fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>);
}

impl CtxtWidget for W1 {
    fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
        unimplemented!()
    }
}
impl CtxtWidget for W2 {
    fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
        unimplemented!()
    }
}

impl<'c> Widget<Ctxt<'c>> for Box<CtxtWidget> {
    fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
        self.ctxt_f(ctx);
    }
}

struct WV {
    pub widgets: Vec<Box<CtxtWidget>>,
}

fn main() {
    let mut wv = WV{widgets: Vec::new()};
    wv.widgets.push(Box::new(W1{}));
    wv.widgets.push(Box::new(W2{}));
    let u = 65u32;
    let mut ctxt = Ctxt{data: &u};
    for widget in &wv.widgets {
        widget.f(&mut ctxt);
    }
}

playground

实际上CtxtWidget大致相当于for<'c> Widget<Ctxt<'c>>

我仍然对任何其他解决方案感兴趣(如果有更好的方法可以进行侵入式更改)。