我对上下文类型进行了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
指定任何生命周期。
如何存储特征的多个实现者,这些实现者允许传入包含引用的上下文?
答案 0 :(得分:3)
Ctxt
和CtxtWidget
间接选择新的特征来推迟选择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);
}
}
实际上CtxtWidget
大致相当于for<'c> Widget<Ctxt<'c>>
。
我仍然对任何其他解决方案感兴趣(如果有更好的方法可以进行侵入式更改)。