如何基于uom crate的Quantity类型别名实现单泛型参数包装
问题:用单个泛型参数包装uom的Quantity类型别名
我使用的crate定义了基础类型Quantity<D,U,V>及多个类型别名,例如:
type Length = Quantity<Dim::L, Meter, f64>;
我希望定义泛型函数或结构体来包装Quantity,但仅接受这些类型别名作为单个泛型参数,而非重复指定D、U、V三个参数。期望实现的结构与函数如下:
struct ParsedQuantity<Q> { quantity: Q, additional_field: Something } fn parse_value<Q>(s: &str) -> Result<ParsedQuantity<Q>, &str>;
其中Q代表上述类型别名,以便能这样使用:
struct Model { mass: ParsedQuantity<Mass> } let mass = parse_value::<Mass>("1 kg");
如果直接返回Quantity,借助Rust类型推断,即使函数签名为parse_value<D, U, V>也能正常工作:
pub fn parse_value<D, U, V>(s: &str) -> Result<Quantity<D, U, V>, &str> where D: Dimension + ?Sized, U: uom::si::Units<V> + ?Sized, V: uom::Conversion<V> + uom::num_traits::Num, Quantity<D, U, V>: FromStr, { /* ... */ } let parsed: Length = parse_value("1 m").unwrap();
这里D、U、V能被正确推断,但返回包装结构体ParsedQuantity时,类型无法便捷推断,必须手动指定三个类型参数,这不是我想要的结果。
请问该如何操作,才能让函数或结构体接受Q = Quantity<D,U,V>这类别名作为单个泛型参数,而非三个参数?
解决方案
可以通过定义关联Quantity内部参数的trait,将三个参数的约束转移到单个泛型参数上,实现需求。
1. 定义标记trait并自动实现
先定义一个trait,为所有合法的Quantity类型关联出内部的D、U、V参数,并自动为所有Quantity实例实现该trait:
use uom::{Dimension, Conversion}; trait IsQuantity { type Dim: Dimension + ?Sized; type Units: uom::si::Units<Self::Value> + ?Sized; type Value: Conversion<Self::Value> + uom::num_traits::Num; } // 为所有Quantity<D,U,V>自动实现IsQuantity impl<D, U, V> IsQuantity for Quantity<D, U, V> where D: Dimension + ?Sized, U: uom::si::Units<V> + ?Sized, V: Conversion<V> + uom::num_traits::Num, { type Dim = D; type Units = U; type Value = V; }
2. 用trait约束泛型参数
现在可以在结构体和函数中使用单个泛型参数Q,通过IsQuantity trait确保它是合法的Quantity类型:
// 示例包装结构体 struct ParsedQuantity<Q> { quantity: Q, additional_field: String, } // 单个泛型参数的解析函数 fn parse_value<Q>(s: &str) -> Result<ParsedQuantity<Q>, &str> where Q: IsQuantity + std::str::FromStr<Err = &'static str>, { let quantity = s.parse()?; Ok(ParsedQuantity { quantity, additional_field: "解析成功".to_string(), }) }
3. 使用示例
直接用类型别名作为泛型参数即可,无需手动指定三个内部参数:
// 假设已定义的类型别名 type Mass = Quantity<Dim::Mass, Kilogram, f64>; struct Model { mass: ParsedQuantity<Mass>, } fn main() { // 显式指定泛型参数 let mass = parse_value::<Mass>("1 kg").unwrap(); println!("解析后的质量: {:?}", mass.quantity); // 或通过返回值类型自动推断 let inferred_mass: ParsedQuantity<Mass> = parse_value("2 kg").unwrap(); }
内容的提问来源于stack exchange,提问作者Lyss
相关产品推荐
相关产品推荐

