11.5 Advanced Generics
Generics in Rust provide powerful ways to write reusable, performance-oriented code. This section covers some advanced features—associated types in traits, const generics, and how monomorphization influences performance.
11.5.1 Associated Types in Traits
We’ve seen that Iterator
uses an associated type, type Item
, to indicate what each iteration yields. This strategy prevents you from having to write:
trait Iterator<T> {
fn next(&mut self) -> Option<T>;
}
Instead, an associated type Item
keeps the trait interface cleaner:
#![allow(unused)] fn main() { trait Container { type Item; fn contains(&self, item: &Self::Item) -> bool; } struct NumberContainer { numbers: Vec<i32>, } impl Container for NumberContainer { type Item = i32; fn contains(&self, item: &i32) -> bool { self.numbers.contains(item) } } }
11.5.2 Const Generics
Const generics let you specify constants (such as array sizes) as part of your generic parameters:
struct ArrayWrapper<T, const N: usize> { elements: [T; N], } fn main() { let array = ArrayWrapper { elements: [0; 5] }; println!("Array length: {}", array.elements.len()); }
11.5.3 Generics and Performance
Rust’s monomorphization process duplicates generic functions or types for each concrete type used, leading to specialized, optimized machine code. As in C++ templates, this often means:
- Zero-Cost Abstractions: The compiled program pays no runtime penalty for using generics.
- Potential Code Size Increase: Widespread usage of generics with many different concrete types can inflate the final binary.