That's sort of true, but it really depends on what you're comparing to what.
For example, yet another thing you could do here is make an
enum Component with variants carrying
Velocity values, then you could trivially write the
match block you originally thought of writing. Of course, that would no longer be "compile-time polymorphism", so all the component values but be carrying around a variant tag and doing a match at runtime (which may or may not be negligible in your program).
IMO, the difference that's really conceptually important here is that an
enum is a closed set of possible variants, meaning all of the options are declared exactly once and none can be added from elsewhere after that declaration. On the other hand, a
trait is an open set of possible types, so there could be any number of
impls of that trait all over your code, and even in your users' code, so in principle the compiler may never get to see all of the
impls at the same time.
That openness is precisely why this "inversion" makes sense: Adding a new trait impl only requires writing only the one
impl block, without touching any of the other
impls or the generic call sites. Adding a new
enum variant typically requires touching every single
if let using the
This feels like a difference from C++ primarily because C++ does not require concepts on type parameters, while Rust requires traits on its type parameters. The tradeoff here is that C++ is less typesafe and has less helpful error messages. In Rust, if you try to
std::sort an unsortable type
T, you're going to get a fairly straightforward "
T doesn't impl
Ord" error. In C++, you either get silently wrong behavior (maybe even UB!), or if you're lucky you get a "post-monomorphization error" such as "on line 42 of the
std::sort implementation it says
x > y which we can't compile because there's no
operator> for types
Y, which you've never heard of before, but that's because
X was implicitly derived from your
T through..." and so on and so forth. This is why C++ concepts are often marketed as "improving template errors".
Hopefully that helps make it all seem a little more deliberate and not just an arbitrary difference from C++.