rust `matrix::Matrix〈1,1,_>`的冲突实现

tquggr8v  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(111)

我的矩阵实现

pub struct Matrix<const M: usize, const  N: usize, T: Num + Neg + Copy>(Box<[[T; N]; M]>);

impl<const M: usize, const  N: usize, T: Num + Neg + Copy> Index<(usize, usize)> for  Matrix<{M}, {N}, T> {
    type Output = T;

    fn index(&self, index: (usize, usize)) -> &Self::Output {
        &self.0[index.0][index.1]
    }
}

由矩阵定义列向量和行向量

type CVector<const N: usize, T> = Matrix<{1}, {N}, T>;
type RVector<const N: usize, T> = Matrix<{N}, {1}, T>;
impl<const N: usize, T: Num + Neg + Copy> Index<usize> for CVector<{N}, T> {
    type Output = T;

    fn index(&self, index: usize) -> &Self::Output {
        &self[(0,index)]
    }
}

impl<const N: usize, T: Num + Neg + Copy> Index<usize> for RVector<{N}, T> {
    type Output = T;

    fn index(&self, index: usize) -> &Self::Output {
        &self[(index,0)]
    }
}

错误

error[E0119]: conflicting implementations of trait `Index<usize>` for type `matrix::Matrix<1, 1, _>`
  --> src/vector.rs:38:1
   |
30 | impl<const N: usize, T: Num + Neg + Copy> Index<usize> for CVector<{N}, T> {
   | -------------------------------------------------------------------------- first implementation here
...
38 | impl<const N: usize, T: Num + Neg + Copy> Index<usize> for RVector<{N}, T> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `matrix::Matrix<1, 1, _>`

我知道模板专业化现在还不稳定。有什么技巧可以解决这个问题吗?
我尝试了模板专业化。

wnvonmuf

wnvonmuf1#

即使有了专门化,由于冲突,这些实现也是不可能的。不要忘记类型别名仍然与底层类型完全相同,因此impl<...> Index<usize> for CVector<N, T>impl<...> Index<usize> for Matrix<{1}, N, T>完全相同。因此您有以下两种实现:

impl<const N, T> Index<usize> for Matrix<{1}, N, T> { ... }
impl<const N, T> Index<usize> for Matrix<N, {1}, T> { ... }

N == 1的情况下,这里有一个冲突:Index<usize> for Matrix<{1}, {1}, T>的两种实现,并且出于专门化的目的,两者都没有明显地比另一个更“具体”。
我的建议是为RVectorCVector使用新类型:

struct RVector<const N, T>(Matrix<N, {1}, T>);
struct CVector<const N, T>(Matrix<{1}, N, T>);

然后,您可以在这些上使用impl Deref来轻松访问底层矩阵,同时仍然提供专门的向量特定功能,如您的Index实现。使用repr(transparent),您甚至可以添加unsafe访问器,直接从&Matrix<{1}, N, T>转换为&CVector<N, T>,而无需额外复制。
最后,我还建议您使用类似于我在gridly(我的2D网格库)中使用的模式。有很多功能在行和列上重复,因此我使用RowColumn类型而不是usize进行索引,并使用trait Component对它们进行泛化。例如,Grid::single_view可以获取单行或单列的视图(通过调用grid.single_view(Row(2))grid.single_view(Column(4)))。

相关问题