Home
# Types génériques --- ## Généralités - Génériques utilisés pour des fonctions, `struct`, `enums`, ... - Généralisation de concepts présents dans le code. - Réduisent la quantité de code à écrire. --- ## Exemple sans générique ```rust [1-3|4-6|8-10|11-13|] fn max_i32(a: i32, b: i32) -> i32 { if a > b { a } else { b } } fn max_f64(a: f64, b: f64) -> f64 { if a > b { a } else { b } } fn main() { let a = 1; let b = 7; println!("De {} et {}, {} est le plus grand.", a, b, max_i32(a,b)); let a = 1.5; let b = 7.5; println!("De {} et {}, {} est le plus grand.", a, b, max_f64(a,b)); } ``` --- ## Exemple avec générique (concept) ```rust compile_fail [1|2|] fn max
(a: T, b: T) -> T { if a > b { a } else { b } } ``` --- ## Vrai exemple avec générique ```rust // On doit dire au compilateur que T implémente "< , >" fn max
(a: T, b: T) -> T { if a > b { a } else { b } } fn main() { let a = 1; let b = 7; println!("De {} et {}, {} est le plus grand.", a, b, max(a,b)); let a = 1.5; let b = 7.5; println!("De {} et {}, {} est le plus grand.", a, b, max(a,b)); } ``` --- # Dans les `struct` --- ## Un seul type générique ```rust compile_fail [6-7|8|] struct Point
{ x: T, y: T, } fn main() { let int_point = Point{ x: 1, y: 2 }; // i32 point let flt_point = Point{ x: 2.3, y: 4.7 }; // f64 point let does_not_work_point = Point{ x: 1, y: 1.5 }; // oups } ``` --- ## Deux types génériques ```rust struct Point
{ x: T, y: U, } fn main() { let int_point = Point{ x: 1, y: 2}; // i32 point let flt_point = Point{ x: 2.3, y: 4.7}; // f64 point let does_work_now_point = Point{ x: 1, y: 1.5}; // i32, f64 point } ``` --- # Dans les méthodes --- ## Générique ```rust struct Point
{ x: T, y: T, } impl
Point
{ fn get_x(&self) -> &T { &self.x } } fn main() { let point = Point{ x: 1, y: 2}; println!("x = {}", point.get_x()); } ``` --- ## Monomorphisation ```rust struct Point
{ x: T, y: T, } impl Point
{ fn norm(&self) -> f64 { (self.x * self.x + self.y * self.y).sqrt() } } fn main() { let point = Point{ x: 1.0, y: 2.0}; println!("norm = {}", point.norm()); } ``` --- ## Plus générique (lvl 10) ```rust struct Point
{ x: T, y: T, } impl
+ std::ops::Add
+ Copy> Point
{ fn norm_sqr(&self) -> T { self.x * self.x + self.y * self.y } } fn main() { let point = Point{ x: 1.0, y: 2.0}; println!("norm_sqr = {}", point.norm_sqr()); } ``` --- ## `enum`: `SomethingOrNothing
` ```rust // Permet d'avoir un type générique dans Some enum SomethingOrNothing
{ Something(T), Nothing, } fn main() { let int_opt = SomethingOrNothing::Something(4); let char_opt = SomethingOrNothing::Something('a'); } ``` --- ## Que fait le compilateur? - A la compilation le type générique est remplacé par un type spécifique: monomorphisation. - Pour chaque type, le compilateur crée une version de la fonction, struct, ... - Et remplace la fonction générale par le code spécialisé. - Aucun coût à l'exécution.