Generics
Generics let you write code once and use it with many types. A generic type is written as a name in angle brackets, usually T.
Generic functions
Put <T> after the function name. Then T can stand for any type.
fn first<T>(a: T, b: T) -> T { a}first(1, 2); // T is i32first("x", "y"); // T is &strBoth a and b are T, so they must be the same type in one call. Without a bound (next unit), you can only move, return or store a T.
Generic structs
A struct can take a type too.
struct Point<T> { x: T, y: T,}let a = Point { x: 1, y: 2 }; // Point<i32>let b = Point { x: 1.5, y: 2.0 }; // Point<f64>x and y share one T, so Point { x: 1, y: 2.0 } fails with E0308. Use two parameters, Point<T, U>, if the fields may differ.
Generic impl blocks
Write impl<T> to add methods for every T.
impl<T> Point<T> { fn x(&self) -> &T { &self.x }}The first <T> declares the name. The second one, in Point<T>, uses it.
Zero-cost generics
The compiler looks at each type you use with a generic. It writes a separate copy of the code for each one. This is called monomorphization. So first(1, 2) and first("x", "y") use two plain functions: one for i32 and one for &str. There is no extra cost when the program runs. The cost is a bit more compile time and a bigger program.
Remember
<T>declares a type parameter; oneTmeans one type.struct Name<T>andimpl<T> Name<T>work the same way.- Generic code is copied per type at compile time, so it runs as fast as normal code.