为什么 Unsigned 特征不会自动给出 Rust 中的 One 特征?

Jak*_* W. 4 types traits rust

我想编写以下形式的通用函数

fn my_function<T: num::Unsigned>(T: number) -> T
Run Code Online (Sandbox Code Playgroud)

为了将它们用于所有无符号整数类型,所以u8- u128。然而,我经常想做一些类似的事情

let n = number + 1;
Run Code Online (Sandbox Code Playgroud)

或者

let mut n = number;
number -= 1;
Run Code Online (Sandbox Code Playgroud)

在函数体中。现在,每次我使用类似的东西时,Rust 都会告诉我 -trait std::ops::SubAssignstd::cmp::PartialOrd-trait 等并未针对T.

有没有一种简单的方法来指定我的号码只是其中一种类型u8-u128因此具有所有这些特征?为什么 Rust 编译器不清楚这一点,即Unsigned不具有PartialOrd-trait 的 -type 的示例是什么?

编辑:澄清一下:我想要的是一种方式来表达“T必须具有其中一种类型u8...... u128(也许BigUInt)”,然后让 Rust 自动看到“因为T是其中一种类型,所以以下特征具有实施对象Tstd::cmp::PartialOrd, std::ops::SubAssign, ...”

kmd*_*eko 6

反之,T: Unsigned 表示T: One. Unsigned是 的超级特征,Num是 的超级特征ZeroOne是 、 等的超级特征:

pub trait Unsigned: Num { }
pub trait Num: Zero + One + NumOps<Self, Self> + PartialEq<Self> { ... }
Run Code Online (Sandbox Code Playgroud)

要理解的关键是,这1与 不同T::one()。这适用于例如:

use num::Unsigned; // 0.4.0

fn my_function<T: Unsigned>(number: T) -> T {
    number + T::one()
}
Run Code Online (Sandbox Code Playgroud)

NumOps特征意味着定义了各种算术运算符,但仅在Ts 之间定义。字面意思1可能不是 a TT可能是类似 的东西BigUint


我想要的是一种方式来表达“T必须具有其中一种类型u8...... u128(也许BigUInt)”,然后让 Rust 自动看到“因为T是这些类型之一,所以必须实现以下特征Tstd::cmp::PartialOrd、、std::ops::SubAssign……”

这不是特质的设计原理。特征可以在外部类型上实现,所以即使现在Unsigned只为这些类型实现,其他一些板条箱我也会为它们的类型实现它,这些类型不具有...的所有相同属性,等等。u8u128

相反,您应该限制 T拥有函数运行所需的属性。所以你必须明确。

  • @雅各布W。`&lt;left&gt; += &lt;right&gt;` 不能是 `&lt;left&gt; = &lt;left&gt; + &lt;right&gt;` 的简写,因为 `&lt;left&gt;` 可以是复杂的表达式,例如 `map.get(key).unwrap ()[current_col].value`,您不想为了效率和可能的副作用而评估两次。另外,对于bigints这样的类型,实际上可以通过修改现有值来实现就地加法;在这种情况下,将“big += 1”实现为“big = big + 1”将不必要地创建一个新的 bigint 并丢弃旧的。 (2认同)