如何在 Rust 中指定值约束?

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:我确信我的方法不是最佳实践,但是标准的替代方法是什么?

Mat*_* M. 6

但最好定义一个新类型,在赋值时为我执行此检查,类似于默认情况下整数不能溢出的方式。

这确实是最好的。

您可以将其定义为用户类型:

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