Generic types versus trait objects

We can use trait objects in a very similar way to generic type parameters. From one point of view, these two functions do the same thing:

fn print_generic<T>(value: T) where T: Display {
println!("{}", value);
}

This might seem like it does the same thing as the previous code:

fn print_trait(value: &dyn Display) {
println!("{}", value);
}

The first has a generic type parameter with a trait bound, the second accepts a trait object, which means both of them can work with many different data types, as long as the type in question has the Display trait.

Underneath, though, they're very different. The generic function is used to generate a version of the function that is specialized for each data type that is passed to it, while the compiler is running. That means that when we call the function while the program is running,the computer doesn't have to spend any time at all considering the differences between various data types. It just calls the function the compiler told it to use, which is the version specialized for the data type that's actually being used. This is faster, but all the various versions of generic functions make the program a little larger.

This process of turning a generic type-based pattern for a function into multiple actual functions specialized for specific types is called monomorphization.

The function that accepts a trait object as its parameter, on the other hand, has only one version, but the computer has to deal with the differences between the various data types that have the Display trait while it's running. This is slower, but requires a little less memory.

As a rule of thumb, opt to use generic type parameters when you can. We do things at runtime when they can't be done at compile time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.235.62