C++背景学习Rust,如何实现可接收泛型类型参数的泛型代码
问题解决:Rust实现类似C++模板模板参数的泛型功能
核心原因
你遇到的type argument not allowed报错是因为Rust稳定版没有原生支持C++那种模板模板参数(也就是可以接收泛型类型作为参数的泛型参数),对应的概念在类型系统中叫高阶类型(Higher-Kinded Types, HKT),Rust目前可以通过1.65版本后稳定的**泛型关联类型(Generic Associated Types, GAT)**模拟实现对应能力。
代码实现
1. 修正Monad trait定义
通过泛型关联类型声明“套入任意类型参数T后的自身类型”,替代直接写Self<T>的写法:
trait Monad { /// 泛型关联类型:代表当前类型套上类型参数T后的结果 type Wrapped<T>; fn singleton<T>(t: T) -> Self::Wrapped<T>; fn compact<T>(mmt: Self::Wrapped<Self::Wrapped<T>>) -> Self::Wrapped<T>; }
2. 给具体泛型类型实现Monad trait
以Option、Vec为例:
impl Monad for Option { type Wrapped<T> = Option<T>; fn singleton<T>(t: T) -> Self::Wrapped<T> { Some(t) } fn compact<T>(mmt: Self::Wrapped<Self::Wrapped<T>>) -> Self::Wrapped<T> { mmt.flatten() } } impl Monad for Vec { type Wrapped<T> = Vec<T>; fn singleton<T>(t: T) -> Self::Wrapped<T> { vec![t] } fn compact<T>(mmt: Self::Wrapped<Self::Wrapped<T>>) -> Self::Wrapped<T> { mmt.concat() } }
3. 实现对应C++示例的id函数
泛型参数约束为实现了Monad trait的类型,通过关联类型指定参数和返回值:
fn id<F: Monad>(fi: F::Wrapped<i8>) -> F::Wrapped<i8> { fi }
4. 测试调用
fn main() { // 测试Option场景 let opt_val = Some(10i8); assert_eq!(id::<Option>(opt_val), Some(10i8)); // 测试Vec场景 let vec_val = vec![1i8, 2i8, 3i8]; assert_eq!(id::<Vec>(vec_val), vec![1i8, 2i8, 3i8]); }
注意事项
- 上述写法可覆盖绝大多数C++模板模板参数的使用场景,和原生HKT的差异仅在于需要通过关联类型访问包裹后的类型,没有额外运行时开销
- 如果需要更高阶的抽象,也可以使用第三方库提供的HKT封装,但GAT已经足够解决常规需求
内容的提问来源于stack exchange,提问作者user13507303
相关产品推荐
相关产品推荐

