Rust
Beginner
1 min read
Generic Bounds, where Clauses, and Associated Types
Example
use std::fmt::{Debug, Display};
use std::ops::Add;
// Multiple bounds with where clause
fn format_sum<T>(a: T, b: T) -> String
where
T: Add<Output = T> + Display + Copy,
{
let sum = a + b;
format!("{a} + {b} = {sum}")
}
// Associated type in a custom trait
trait Transformer {
type Input;
type Output;
fn transform(&self, input: Self::Input) -> Self::Output;
}
struct Doubler;
impl Transformer for Doubler {
type Input = i32;
type Output = i32;
fn transform(&self, input: i32) -> i32 { input * 2 }
}
struct Stringify;
impl Transformer for Stringify {
type Input = i32;
type Output = String;
fn transform(&self, input: i32) -> String { format!("#{input}") }
}
// Generic function constrained on the Transformer trait
fn apply<T: Transformer>(t: &T, input: T::Input) -> T::Output {
t.transform(input)
}
// Bound on a generic struct
#[derive(Debug)]
struct DisplayVec<T: Display>(Vec<T>);
impl<T: Display> DisplayVec<T> {
fn print_all(&self) {
for (i, item) in self.0.iter().enumerate() {
println!(" [{i}] {item}");
}
}
}
fn main() {
println!("{}", format_sum(3, 4));
println!("{}", format_sum(1.5_f64, 2.5));
let d = Doubler;
let s = Stringify;
println!("doubled: {}", apply(&d, 21));
println!("stringified: {}", apply(&s, 42));
let dv = DisplayVec(vec!["alpha", "beta", "gamma"]);
dv.print_all();
}