When one already knows all the finite number of types involved in some code which needs dynamic polymorphism, using enum
can be better for performances compared to using Box
since the latter uses dynamic memory allocation and you'll need to use trait objects which have virtual function call as well.
That said, compared to the equivalent code in C++ using std::variant
and std::visit
, looks like Rust in this scenario has more boilerplate coding involved, at least for me (I have not yet learned to use procedural macros). Making some example here: I have a bunch of struct
types:
struct A {
// ...
}
struct B {
// ...
}
// ...
struct Z {
// ...
}
They all implement the trait AlphabetLetter
which is:
trait AlphabetLetter {
fn some_function(&self);
}
Since the set of types involved is known and limited, I want to use enum
:
enum Letter {
AVariant(A),
BVariant(B),
// ...
ZVariant(Z),
}
Already here we have the first boilerplate: I need to add a name for the enum
value for every type variant involved. But the real issue is: enum
Letter
is itself an AlphabetLetter
, it just represent the fact that we do not know at runtime which letter it is. So I started implementing the trait for it:
impl AlphabetLetter for Letter {
fn some_function(&self) {
match self {
Letter::AVariant(letter) => letter.some_function();
Letter::BVariant(letter) => letter.some_function();
// ...
Letter::ZVariant(letter) => letter.some_function();
}
}
}
And yes, this can become easily a lot of code, but I found no other way of doing it. In C++, thanks to generic lambdas, one can just std::visit
a std::variant
and it's a one liner. How can I do the same without manually writing all the pattern matching for every function in the traits X every variant in the enum
?