I just started learning Rust some days ago and, coming from a C/C++/C# background, immediately stubbed my toe on the type system. The notion of traits, however, is something I really like and allows for a stunt that is impossible in C# and ugly in C++: adding things, where by things I mean all the things.
The key is to constrain a generic type parameter with the Add<T>
trait. In this example, I’m constraining a generic type T1
to be Add<T2>
, that is, to be able to add a T2
to itself. The result of such an operation is obviously generic as well, <T1 as Add<T2>>::Output
(with Output
being the type), allowing for the following code:
fn add<T1, T2>(a:T1, b:T2) -> <T1 as Add<T2>>::Output where T1: Add<T2> { a+b }
While this function does nothing more than adding two values of arbitrary types (try that in C# with primitive types), the underlying mechanism allows for interesting operations such as vector-matrix multiplication without having to resort to a concrete type. A Complex
would work as well as a primitive f32
(i.e. float
), f64
(i.e. double
), etc.
You can do this in C++, but instead of having the compiler check the traits (like rustc does), you rather have to hope that someone implemented that specific operator overload or else you’d be in template error message hell.