为了论证的目的,假设我想学习如何构建一个表示2D向量的简单通用 struct .
pub struct Vector<T> {
x: T,
y: T,
}
现在,很明显,我想做一个新的向量:一个给定坐标的向量,零向量,为什么不,甚至是一个单位向量.
impl<T: Default + From<u8>> Vector<T> {
pub fn new(x: T, y: T) -> Self {
Self { x, y }
}
pub fn zero() -> Self {
Self { x: T::default(), y: T::default() }
}
pub fn unit() -> Self {
Self { x: T::from(1), y: T::from(1) }
}
}
让我们试一试这个.
fn main() {
let v1 = Vector<u8>::new(1, 2);
let v2 = Vector<u8>::unit();
}
这工作就像一个魅力.然而,让我们从u8
到i8
fn main() {
let v1 = Vector::<i8>::new(1, 2);
let v2 = Vector::<i8>::unit();
}
然后我们得到以下编译错误
性状界限
i8: From<u8>
不满足
我可以从这里做什么才能使用任何数字类型?
我知道,比方说,可以使用num
crate 中的FromPrimitive
特性.尽管如此,我仍然处于 rust 病的学习阶段,如果可能的话,我想学习如何只用STD来做到这一点.
那么,让我们开始实现i8
的From<u8>
.
impl From<u8> for i8 {
fn from(value: u8) -> Self {
value as Self
}
}
好吧,情况并不乐观:
error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> main.rs:17:1
|
1 | impl From<u8> for i8 {
| ^^^^^--------^^^^^--
| | | |
| | | `i8` is not defined in the current crate
| | `u8` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
那么,让我们使用宏吧?
macro_rules! impl_fromu8 {
($($t:ty)*) => {
$(
impl From<u8> for $t {
fn from(value: u8) -> Self {
value as Self
}
}
)*
};
}
impl_fromu8!(i8);
显然,这是相同的代码,所以它不起作用.
目前,我发现的唯一简单的可能性就是创建一个新类型,就像编译器告诉我的那样.还有别的办法吗?