[英]How do I obtain a trait object from a wrapper trait object with an associated type?
我有兩個特征Foo
和Bar
:
trait Bar {
fn get_name(&self) -> &str;
}
trait Foo {
type B: Bar + ?Sized;
fn get_bar(&self) -> &Self::B;
}
實際上,我會有許多不同類型的Foo
和Bar
,但每個Foo
都有一種Bar
類型的相關特征。 現在保持簡單, SimpleFoo
與SimpleBar
相關聯:
struct SimpleBar {
name: String,
}
impl Bar for SimpleBar {
fn get_name(&self) -> &str {
&self.name
}
}
struct SimpleFoo {
bar: Rc<SimpleBar>,
}
impl Foo for SimpleFoo {
type B = SimpleBar;
fn get_bar(&self) -> &SimpleBar {
&self.bar
}
}
在某些地方我可以使用 generics 和單態,但在某些地方我需要動態調度,比如這個 function 比需要一個dyn Foo
其Bar
是一個dyn Bar
:
fn some_func_that_needs_dyn_foo_returning_a_dyn_bar(foo: &dyn Foo<B = dyn Bar>) {
// do stuff
}
由於SimpleFoo
實現Foo<B = SimpleBar>
而不是Foo<B = dyn Bar>
我不能直接傳遞它(我希望編譯器或派生或其他東西可以在這里做魔術並使這成為可能),所以我有一個包裝器 class它持有對某些特定Foo
的引用,並且可以獲得其特定的Bar
並將其變成dyn Bar
:
struct DynamicFooWrapper<'a, F: Foo> {
foo: &'a F,
}
impl<'a, F> Foo for DynamicFooWrapper<'a, F>
where
F: Foo,
<F as Foo>::B: Sized,
{
type B = dyn Bar;
fn get_bar(&self) -> &'a Self::B {
self.foo.get_bar()
}
}
fn main() {
let b = Rc::new(SimpleBar {
name: "Bar101".to_owned(),
});
let f = SimpleFoo { bar: b.clone() };
some_func_that_needs_dyn_foo_returning_a_dyn_bar(&DynamicFooWrapper { foo: &f })
}
對返回生命周期的不滿在於包裝器的實現:
error[E0310]: the associated type `<F as Foo>::B` may not live long enough
--> src/main.rs:45:9
|
45 | self.foo.get_bar()
| ^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<F as Foo>::B: 'static`...
= note: ...so that the type `<F as Foo>::B` will meet its required lifetime bounds
For more information about this error, try `rustc --explain E0310`.
我不想在這里有任何 static 數據。 我想將此處返回的&dyn Bar
的生命周期與DynamicFooWrapper
包裝的foo
的生命周期聯系起來,因為&dyn Bar
的生命周期至少與包裝的Foo
一樣長。 例如,在Foo
包裝器上調用get_bar()
之后,我什至想銷毀Foo
包裝器,只要原始Foo
項目還活着。 這應該是可能的,因為這保證了Bar
的生命周期——我只是不確定如何表達這一切。
TL/DR:您需要使用dyn Bar + 'a
而不是普通的dyn Bar
:
fn some_func_that_needs_dyn_foo_returning_a_dyn_bar<'a>(_foo: &dyn Foo<B=dyn Bar + 'a>) {
// do stuff
}
struct DynamicFooWrapper<'a, F: Foo> {
foo: &'a F,
}
impl<'a, F> Foo for DynamicFooWrapper<'a, F>
where
F: Foo,
<F as Foo>::B: Sized,
{
type B = dyn Bar + 'a;
fn get_bar(&self) -> &'a Self::B {
self.foo.get_bar()
}
}
fn main() {
let b = Rc::new(SimpleBar {name: "Bar101".to_owned()});
let f = SimpleFoo { bar: b.clone() };
some_func_that_needs_dyn_foo_returning_a_dyn_bar(&DynamicFooWrapper{foo: &f})
}
在某些時候, dyn Bar + 'a
將與某個具體類型T
匹配。 + 'a
約束告訴編譯器,如果T
包含引用,那么這些引用至少與'a
一樣長。 如果你想引用T
的生命周期'a
就像在&'a Self::B
中那樣,這是必需的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.