问题描述
我有一个特征 Foo
,有一些实现,还有一个枚举 Foos
,每个实现都有一个变体。我希望能够将我的枚举转换为 Box< dyn Foo>
。
I have a trait Foo
, with some implementations, together with an enum Foos
with one variant per implemention. I want to be able to convert my enum into Box<dyn Foo>
.
这是我当前的解决方案:
This is my current solution:
trait Foo {}
struct FooA {}
impl Foo for FooA {}
struct FooB {}
impl Foo for FooB {}
struct FooC {}
impl Foo for FooC {}
enum Foos {
A(FooA),
B(FooB),
C(FooC),
}
impl Foos {
fn into_box(self) -> Box<dyn Foo> {
match self {
Foos::A(foo) => Box::new(foo),
Foos::B(foo) => Box::new(foo),
Foos::C(foo) => Box::new(foo),
}
}
}
可以,但是 into_enum
中有很多样板。随着变体数量的增加,功能也会随之增加。有没有更简单的方法可以做到这一点?
It works, but there's a lot of boiler plate in into_enum
. As the number of variants grow, so will the function. Is there a simpler way to do this? It feels like it should be a one liner!
推荐答案
使用,您可以编写
With the enum_dispatch
crate, you can write
#[macro_use]
extern crate enum_dispatch;
#[enum_dispatch]
trait Foo {}
struct FooA {}
impl Foo for FooA {}
struct FooB {}
impl Foo for FooB {}
struct FooC {}
impl Foo for FooC {}
#[enum_dispatch(Foo)]
enum Foos {
A(FooA),
B(FooB),
C(FooC),
}
获取生成的 Impl Foo for Foos
。然后,您可以将 Foos
转换为 Box< dyn Foo>
,只需使用 Box :: new
。
to get a generated impl Foo for Foos
. You can then convert Foos
to Box<dyn Foo>
with simply Box::new
.
此方法有潜在的缺点: Box :: new(Foos :: A(FooA))
包含 Foos
,而不是 FooA
,因此这将导致这两个从 dyn Foo
到 Foos
的动态调度和 enum
调度从 Foos
到 FooA
。
There is a potential downside to this approach: Box::new(Foos::A(FooA))
contains a Foos
, not an FooA
, so it will incur the overhead of both the dynamic dispatch from dyn Foo
to Foos
and the enum
dispatch from Foos
to FooA
.
,现在您已经有 impl Foo for Foos
:凡是使用 Box< dyn Foo>
的地方,而是可以直接使用 Foos
,这在每种方式上都应该更有效率。
On the other hand, now that you have impl Foo for Foos
: everywhere you would have used Box<dyn Foo>
, you’ll instead be able to directly use Foos
, which should be more efficient in every way.
这篇关于将所有变体实现相同特征的枚举转换为Rust中的框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!