Rust中Unsigned trait为何未自动实现PartialOrd等常用trait?
问题解答
泛型约束的简便实现方案
你可以通过组合trait约束的方式实现需求,同时兼容内置无符号整数和BigUInt:
- 优先推荐自定义组合trait,后续复用更方便:
use num::Unsigned; use std::ops::{AddAssign, SubAssign, PartialOrd, One}; // 把所有你需要的能力都组合到自定义trait里 trait ValidUnsigned: Unsigned + PartialOrd + AddAssign<Self> + SubAssign<Self> + One + Copy {} // 为所有满足条件的类型自动实现该trait impl<T: Unsigned + PartialOrd + AddAssign<T> + SubAssign<T> + One + Copy> ValidUnsigned for T {} // 函数直接用组合后的trait做约束即可 fn my_function<T: ValidUnsigned>(number: T) -> T { let mut n = number; n += T::one(); // 泛型场景下不能直接写整数字面量,要调用One trait的one()方法获取对应类型的1 n -= T::one(); n }
- 如果只是单次使用不想定义新trait,也可以直接把所有约束写在函数签名上,只是可读性稍差。
编译器无法自动推断的原因
Rust的trait遵循正交设计原则,每个trait仅描述最小范围的能力,num::Unsigned的定义本身就没有继承PartialOrd、SubAssign这类操作trait,所以编译器不会做超出trait定义范围的假设,否则会破坏类型系统的严谨性。
实现了Unsigned但未实现PartialOrd的类型示例
这类类型是合法存在的,比如你可以自定义一个无符号整数包装类型,仅实现Unsigned要求的最小能力集合,故意不实现比较、赋值运算相关trait:
use num::{Unsigned, Zero, One}; use std::ops::{Add, Sub, Mul, Div, Rem}; #[derive(Clone, Copy, Default)] struct CustomUnsigned(u64); // 仅实现Unsigned要求的必要trait impl Add for CustomUnsigned { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl Sub for CustomUnsigned { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) } } // 省略Mul、Div、Rem、Zero、One的实现,均转发内部u64逻辑即可 impl Unsigned for CustomUnsigned {} // 此处故意不实现PartialOrd、SubAssign等trait
上述CustomUnsigned完全满足Unsigned约束,但完全不支持你代码里用到的比较、减法赋值操作,这就是编译器必须要求你显式声明对应约束的原因。
内容的提问来源于stack exchange,提问作者Jakob E.
相关产品推荐
相关产品推荐

