如何为Rust泛型结构体Field实现通用Mul等运算符?
问题:为泛型结构体Field实现通用Mul运算避免嵌套递归错误
需求概述
我定义了带可序列化doc字段的泛型结构体Field<T>,希望Field实例能像内部包含的T类型一样支持运算(以Mul为例):比如f64与Field<f64>相乘输出f64,f64与Field<uom::si::Quantity>相乘输出Quantity等。
已实现的部分Mul逻辑
impl<A, B, C> Mul<B> for &Field<A> where A: Mul<B, Output = C> + Copy { type Output = C; fn mul(self, other: B) -> C { self.val * other } } // 仅针对f64的实现 impl<B, C> Mul<&Field<B>> for f64 where f64: Mul<B, Output = C>, B: Copy { type Output = C; fn mul(self, other: &Field<B>) -> C { self * other.val } }
通用实现遇到的问题
当替换为通用版本时,编译器出现递归错误,要求为&Field<&Field<&Field<...>>>等嵌套类型实现Mul,但我不需要支持Field嵌套场景:
// 存在问题的通用实现 impl<A, B, C> Mul<&Field<B>> for A where A: Mul<B, Output = C>, B: Copy { type Output = C; fn mul(self, other: &Field<B>) -> C { other.val * self } }
完整测试代码
use core::ops::Mul; #[derive(Debug)] struct Field<T> { val: T, } impl<T> Field<T> { fn new(val: T) -> Self { Self { val } } } fn main() { let a = Field::new(1.5); let b = Field::new(2.0); println!("field0 * field1 = {}", &a * &b); println!("4.0 * field1 = {}", 4.0 * &b); println!("field0 * 3.0 = {}", &a * 3.0); } // 已实现的Mul逻辑和有问题的通用实现...
解决方案
要避免递归匹配嵌套Field类型,可以通过标记trait约束来限制A不能是Field或其引用类型,具体步骤如下:
1. 定义标记trait并为非Field类型实现
// 标记trait:表示类型不是Field或其引用 pub trait NotField {} // 为所有类型默认实现,除了Field和&Field impl<T> NotField for T where T: ?Sized {} impl<T> !NotField for Field<T> {} impl<T> !NotField for &Field<T> {}
2. 修改通用Mul实现,添加NotField约束
impl<A, B, C> Mul<&Field<B>> for A where A: Mul<B, Output = C> + NotField, B: Copy { type Output = C; fn mul(self, other: &Field<B>) -> C { self * other.val } }
3. 补充Field与Field相乘的实现
为了支持&Field<A> * &Field<B>的场景,需要额外实现:
impl<A, B, C> Mul<&Field<B>> for &Field<A> where A: Mul<B, Output = C> + Copy, B: Copy { type Output = C; fn mul(self, other: &Field<B>) -> C { self.val * other.val } }
这样修改后,编译器就不会再尝试匹配嵌套的Field类型,同时保留了所有非Field类型与Field相乘的能力,也支持了Field之间的相乘操作。
内容的提问来源于stack exchange,提问作者Kyle Carow
相关产品推荐
相关产品推荐

