neb*_*ars 8 types constraints rust
我正在寻找一种将类型约束转移到某种包装器中的方法。例如,在 Ada 中您可能会看到如下内容:
type Element is Integer range 100 .. 1000;
Run Code Online (Sandbox Code Playgroud)
它定义了一种新类型Element,尽管它仍然是整数,但它绑定到特定范围。还有mod一个会循环回来(超级有用)。
在 Rust 中,到目前为止,我一直在我的所有函数中手动检查这一点,即:
if x < 100 || x >= 1000 {
// throw some kind of error
}
Run Code Online (Sandbox Code Playgroud)
但最好定义一个新类型,在赋值时为我执行此检查,类似于默认情况下整数不能溢出的方式。我知道我们没有继承,但也许我可以实现某种特征?
TL;DR:我确信我的方法不是最佳实践,但是标准的替代方法是什么?
但最好定义一个新类型,在赋值时为我执行此检查,类似于默认情况下整数不能溢出的方式。
这确实是最好的。
您可以将其定义为用户类型:
struct BoundedU16<const MIN: u16, const MAX: u16>(u16);
Run Code Online (Sandbox Code Playgroud)
然后定义您期望的所有方法,从 new 开始:
impl<const MIN: u16, const MAX: u16> BoundedU16<MIN, MAX> {
pub const fn new(value: u16) -> Result<Self, BoundError> {
if value >= MIN && value <= MAX {
Ok(Self(value))
} else {
Err(BoundError(value, MIN, MAX))
}
}
}
Run Code Online (Sandbox Code Playgroud)
主要缺点是目前您无法拥有BoundedInteger<T, const MIN: T, const MAX: T>. 解决方法是使用宏来定义多个Bounded[I|U][8|16|32|64|size].
然后就可以声明了type Element = BoundedU16<100, 1000>;。
但请注意,anyElement在这里只是一个别名,而不是新类型。如果您声明一个新类型,那么struct Element(BoundedU16<100, 1000>)您需要再次实现(或派生)所有特征。
特征允许您添加validate方法,但不允许您自动实现Add、...。这是一个较差的解决方案。Subvalidate