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),
}
}
}
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!
The easiest way to convert an enum to a String in Rust is to implement the std::fmt::Display trait. Then you can call the to_string() method.
In Rust, methods cannot only be defined on structs, they can also be defined on tuples and enums, and even on built-in types like integers.
The enum keyword allows the creation of a type which may be one of a few different variants. Any variant which is valid as a struct is also valid as an enum .
To initialize an enum with values, we assign the enum with a value to a variable. We write the enum name, followed by double colon operators and the enum value name. Lastly, we specify a value between parentheses. In the example above, we assign 1 to Enabled and 0 to Disabled in the variables yes and no.
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),
}
to get a generated impl Foo for Foos
. You can then convert Foos
to Box<dyn Foo>
with simply Box::new
.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With