使用 Rust 空类型作为泛型绑定
Using Rust empty type as a generic bound
如何将 Rust 泛型类型约束为空类型?我需要创建一个具有可选值的类型,这样如果泛型类型是 ()
,它就不会使用任何内存。这是一个简单的示例 - Data
可以是 i32, ()
(4 个字节),也可以是 i32, i32
(8 个字节)。两种情况都有 add()
。我收到此错误(这是有道理的,但不确定如何避免)。我需要处理所有有效的数字类型。
error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Data<(), ()>`
...
note: upstream crates may add a new impl of trait `num_traits::Num` for type `()` in future versions
use num_traits::Num;
trait MyNumericType: Num {}
impl<T: Num> MyNumericType for T {}
struct Data<T1: MyNumericType, T2> {
a: T1,
b: T2,
}
impl<T: MyNumericType> Add for Data<T, ()> {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
a: self.a + other.a,
b: (),
}
}
}
impl<T: MyNumericType> Add for Data<T, T> {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
a: self.a + other.a,
b: self.b + other.b,
}
}
}
impl<T1: MyNumericType,T2> Data<T1, T2> {
fn new(a: T1, b: T2) -> Self {
Self { a, b }
}
}
fn main() {
let r1 = Data::new(1, 2) + Data::new(3, 4);
let r2 = Data::new(1, ()) + Data::new(2, ());
}
问题是您无法控制 ()
类型,所以有人可以在您完全不知道并且没有恶意的情况下编写 impl
来破坏您的代码。 Rust 禁止这种远距离操作。
幸运的是,()
是一个非常简单的类型。所以我们可以自己做。
#[derive(Clone, Copy)]
struct MyUnit;
MyUnit
与 ()
基本相同,除了它在 你的 箱子里,而不是 Rust 的 stdlib 和其他人的箱子里。如果有人出现并为 MyUnit
写了一个 impl
,那么他们一定已经将你的箱子作为依赖项,因此他们意识到了风险。然后用 Data<T, MyUnit>
而不是 Data<T, ()>
来写你的 impl
。它仍然是 zero-sized 类型,因此受到与 ()
.
相同的所有优化。
如何将 Rust 泛型类型约束为空类型?我需要创建一个具有可选值的类型,这样如果泛型类型是 ()
,它就不会使用任何内存。这是一个简单的示例 - Data
可以是 i32, ()
(4 个字节),也可以是 i32, i32
(8 个字节)。两种情况都有 add()
。我收到此错误(这是有道理的,但不确定如何避免)。我需要处理所有有效的数字类型。
error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Data<(), ()>`
...
note: upstream crates may add a new impl of trait `num_traits::Num` for type `()` in future versions
use num_traits::Num;
trait MyNumericType: Num {}
impl<T: Num> MyNumericType for T {}
struct Data<T1: MyNumericType, T2> {
a: T1,
b: T2,
}
impl<T: MyNumericType> Add for Data<T, ()> {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
a: self.a + other.a,
b: (),
}
}
}
impl<T: MyNumericType> Add for Data<T, T> {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
a: self.a + other.a,
b: self.b + other.b,
}
}
}
impl<T1: MyNumericType,T2> Data<T1, T2> {
fn new(a: T1, b: T2) -> Self {
Self { a, b }
}
}
fn main() {
let r1 = Data::new(1, 2) + Data::new(3, 4);
let r2 = Data::new(1, ()) + Data::new(2, ());
}
问题是您无法控制 ()
类型,所以有人可以在您完全不知道并且没有恶意的情况下编写 impl
来破坏您的代码。 Rust 禁止这种远距离操作。
幸运的是,()
是一个非常简单的类型。所以我们可以自己做。
#[derive(Clone, Copy)]
struct MyUnit;
MyUnit
与 ()
基本相同,除了它在 你的 箱子里,而不是 Rust 的 stdlib 和其他人的箱子里。如果有人出现并为 MyUnit
写了一个 impl
,那么他们一定已经将你的箱子作为依赖项,因此他们意识到了风险。然后用 Data<T, MyUnit>
而不是 Data<T, ()>
来写你的 impl
。它仍然是 zero-sized 类型,因此受到与 ()
.