Generics 用泛型覆盖traits的实现

Generics 用泛型覆盖traits的实现,generics,matrix,rust,Generics,Matrix,Rust,我通过实现矩阵数学来练习Rust,我遇到了一些障碍。我定义了我认为与矩阵相关的特征 trait Matrix<T> where T : num::Num { fn dim(&self) -> (usize, usize); fn elem(&self, i : usize, j : usize) -> Option<& T>; fn new_const(v: T, rows : usize, cols : u

我通过实现矩阵数学来练习Rust,我遇到了一些障碍。我定义了我认为与矩阵相关的特征

trait Matrix<T> where T : num::Num  {
    fn dim(&self) -> (usize, usize);
    fn elem(&self, i : usize, j : usize) -> Option<& T>; 
    fn new_const(v: T, rows : usize, cols : usize) -> Self where T : Clone;

    fn same_dim<U>(&self, other: &U) -> bool where U : Matrix<T> {
        self.dim() == other.dim()
    }
}
trait矩阵,其中T:num::num{
fn尺寸(和自身)->(使用,使用);
fn elem(&self,i:usize,j:usize)->选项;
fn new_const(v:T,rows:usize,cols:usize)->Self-where T:Clone;
fn相同尺寸(&self,其他:&U)->bool其中U:Matrix{
self.dim()==其他.dim()
}
}
我有一个使用
Vec
的哑实现。我实现了所有的方法并进行了测试。他们都在工作。现在我想简单地将两个矩阵相加。因此,如果不添加我知道将需要的行迭代器,并且不执行我知道将不正确的add实现,我将执行以下操作

impl <T, U> Add for U where T: num::Num, U: Matrix<T> {
    type Output = U;

    fn add(self, _rhs: U) -> U {
        U::new_const(T::zero(), 5, 5)
    }
}
impl为U添加,其中T:num::num,U:Matrix{
类型输出=U;
fn添加(自,右:U)->U{
新常数(T::zero(),5,5)
}
}
但我明白了

lib.rs:41:7: 41:8 error: the type parameter `T` is not constrained by the impl trait, self type, or predicates [E0207]
lib.rs:41 impl <T, U> Add for U where T: num::Num, U: Matrix<T> {
                ^
lib.rs:41:7: 41:8 help: run `rustc --explain E0207` to see a detailed explanation
error: aborting due to previous error
Could not compile `matrix`.
To learn more, run the command again with --verbose.
Compilation failed.
lib.rs:41:7:41:8错误:类型参数'T'不受impl-trait、self-type或谓词的约束[E0207]
lib.rs:41 impl为U添加,其中T:num::num,U:Matrix{
^
lib.rs:41:7:41:8帮助:运行'rustc--explain E0207'查看详细解释
错误:由于上一个错误而中止
无法编译“矩阵”。
要了解更多信息,请使用--verbose再次运行该命令。
编译失败。

对我来说,T似乎受到限制。有人能给我指出正确的方向吗?

T
不受编译器在实现的使用站点上可以看到的信息的限制。通过拥有
trait Matrix
,单个类型可以是多个元素类型的矩阵,也就是说,拥有这两种元素类型是完全合法的在同一程序中,ode>impl矩阵用于Foo和
impl矩阵用于Foo
。如果发生这种情况,则
Foo+Foo
(即使用
Add
实现)无法确定要使用哪个
t
:同时
t=u8
t=u16
工作

我认为解决这个问题的最佳方法是删除
T
type参数:给定类型只是一种元素上的矩阵(即使是泛型的),例如
Vec
T
上的矩阵,其他什么都没有。这就像:给定类型只能生成一种类型的元素

在代码中,这看起来像:

trait Matrix {
    type Elem: num::Num;

    fn dim(&self) -> (usize, usize);
    fn elem(&self, i: usize, j: usize) -> Option<&Self::Elem>;
    // ...
}
但是,这也不起作用,因为它会遇到一致性问题。编译器无法确保
Add
的此实现不会与
Add
的其他实现重叠,因为可以以某种方式为已经有
Add
实现的类型实现
Matrix
。可以解决这个问题通过创建包装类型,并使用
矩阵
特征作为“后备存储”特征,即它“只是”控制内部表示

struct Matrix<T: Storage> {
    x: T
}
trait Storage { // renamed `Matrix` trait
    type Elem;
    fn dim(&self) -> (usize, usize);
    // ...
}
结构矩阵{ x:T } 特征存储{//重命名为'Matrix'特征 类型元素; fn尺寸(和自身)->(使用,使用); // ... } 然后,
矩阵
类型成为添加更多方法和特性实现等的地方

struct Matrix<T: Storage> {
    x: T
}
trait Storage { // renamed `Matrix` trait
    type Elem;
    fn dim(&self) -> (usize, usize);
    // ...
}