gpt4 book ai didi

rust - 如何从具有关联类型的包装特征对象中获取特征对象?

转载 作者:行者123 更新时间:2023-12-05 05:46:11 25 4
gpt4 key购买 nike

我有两个特质 FooBar :

trait Bar {
fn get_name(&self) -> &str;
}

trait Foo {
type B: Bar + ?Sized;

fn get_bar(&self) -> &Self::B;
}

实际上,我会有很多不同类型的 Foo s 和 Bar s 但每个 Foo具有 Bar 类型的关联特征.现在保持简单,SimpleFooSimpleBar 相关联:

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

在某些地方我可以使用泛型和单态,但在某些地方我需要动态调度,比如这个函数需要 dyn Foo谁的Bardyn 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>我不能直接传递它(我希望编译器或派生或其他东西可以在这里做魔术并使这成为可能),所以我有一个包装类,它包含对某些特定 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`.

我不想在这里有任何静态数据。我想绑定(bind) &dyn Bar 的生命周期回到这里 foo 的一生哪个DynamicFooWrapper包装因为&dyn Bar至少会和包裹的一样长Foo .例如,在调用 get_bar() 之后在 Foo 上包装器,我什至想销毁 Foo wrapper 和原来的一样长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})
}

Playground

在某些时候,dyn Bar + 'a 将与一些具体类型 T 匹配。 + 'a 约束告诉编译器,如果 T 包含引用,那么这些引用至少与 'a 一样长。如果你想引用 T 并使用 'a 作为 &'a Self::B 的引用,这是必需的。

关于rust - 如何从具有关联类型的包装特征对象中获取特征对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71220086/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com