文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
8.1 泛型
泛型(generics)是一种类模板技术,允许使用一些在实例化时才指定的类型(参数化类型)。可用于函数、结构体、枚举和方法,极大减少重复代码。
#[derive(Debug)] struct Data<T> { x: T } fn main() { // let a: Data<i32> = Data{ x: 10 }; // let b: Data<f32> = Data{ x: 1.1 }; let a = Data{ x: 10 }; let b = Data{ x: 1.1 }; assert_eq!(a.x, 10); assert_eq!(b.x, 1.1); }
fn main() { // let x = Vec::new(); // ^^^^^^^^ cannot infer type for type parameter `T` let x: Vec<i32> = Vec::new(); let y = Vec::<i32>::new(); }
允许有多个类型参数,如 Rsult<T, E>
。
单态
编译器对泛型进行 单态化 (monomorphization)处理。也就是结合泛型模板和类型参数,生成具体的类型定义。如此,便不会有运行期行为,也不会有任何性能损失。
编译后只有
Data<i32>
和Data<f64>
两个不同类型,并无Data<T>
。
(gdb) ptype a type = struct demo::Data<i32> { x: i32, } (gdb) ptype b type = struct demo::Data<f64> { x: f64, }
即便是函数,也会生成独立代码。
fn test<T>(x: T) -> T { x } fn main() { test(1); test("abc"); }
(gdb) disass/s test(1); => mov edi,0x1 call 0x5555555671c0 <demo::test<i32>> test("abc"); lea rdi,[rip+0xffffffffffffaa4e] mov esi,0x3 call 0x5555555671d0 <demo::test<&str>>
约束
使用特征(trait)约束类型参数,要求其具备特定功能。多个约束以加号相连。
use std::fmt::{Debug, Display}; fn test<T: Debug + Display>(x: T) { println!("{}", x); // Display println!("{:?}", x); // Debug } fn main() { test(1); test("abc"); }
改用 where
表达约束,使代码更清晰易读。
use std::fmt::{Debug, Display}; fn test<A, B>(x: A, y: B) where A: Debug, // 多个依旧用 + 号。 B: Display { println!("x: {:?}, y: {}", x, y); } fn main() { test("abc", 123); }
也可对泛型结构等进行约束。
use std::fmt::{Debug}; #[derive(Debug)] struct Data<T> where T: Debug { x: T } fn main() { let d = Data{x: 1}; println!("{:?}", d); // struct N; // let d = Data{x: N}; // ^^^^ the trait `Debug` is not implemented for `N` }
其他
无参数泛型函数,须显式指定类型。
为避免编译器将尖括号解析成比较运算符,通常写成
func::<T>
。
use std::default::Default; fn default_value<T: Default>() -> T { T::default() } fn main() { assert_eq!(default_value::<i32>(), 0); }
用 const
将常量值模版化。
use std::fmt::Debug; fn print_array<T: Debug, const N: usize>(v: [T; N]) { println!("{:?}", v); } fn main() { print_array([1, 2, 3]); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论