Generics#
<T> declares a type parameter; the caller fills it (or
inference does).
Generic function.
fn first<T>(xs: &[T]) -> Option<&T> {
xs.first()
}
Generic struct and a generic impl block.
struct Container<T> { value: T }
impl<T: Clone> Container<T> {
fn duplicate(&self) -> (T, T) {
(self.value.clone(), self.value.clone())
}
}
Constraints (T: Trait) describe what T must support.
fn print_all<T: std::fmt::Display>(xs: &[T]) {
for x in xs { println!("{x}"); }
}
where clauses are the alternative when constraints get long.
fn merge<T>(a: T, b: T) -> T
where T: std::ops::Add<Output = T>,
{
a + b
}
References#
OOP for trait definitions that drive constraints.
Trait objects for dynamic dispatch via
dyn Trait.