【问题标题】:Mismatched types when implementing a trait实现特征时类型不匹配
【发布时间】:2015-04-29 11:48:29
【问题描述】:

为了学习 Rust,我正在构建自己的 Matrix 类。我对 Add trait 的实现如下:

impl<T: Add> Add for Matrix<T>
{
    type Output = Matrix<T>;

    fn add(self, _rhs: Matrix<T>) -> Matrix<T>
    {
        assert!(self.rows == _rhs.rows && self.cols == _rhs.cols,
                "attempting to add matrices of different sizes");

        let mut res: Matrix<T> = Matrix::<T>{
            rows: self.rows,
            cols: self.cols,
            data : Vec::<T>::with_capacity(self.rows * self.cols),
        };

        for i in 0..self.rows*self.cols{
            res.data.push(self.data[i] + _rhs.data[i]);
        }
        res
   }
}

但我收到以下错误

       Compiling matrix v0.1.0 (file://~/soft/rust/projects/matrix)
src/lib.rs:35:27: 35:54 error: mismatched types:
 expected `T`,
    found `<T as core::ops::Add>::Output`
(expected type parameter,
    found associated type) [E0308]
src/lib.rs:35             res.data.push(self.data[i] + _rhs.data[i]);
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~

根据错误报告,我想我需要在其他地方指出 T 实现了 Add 特征,但是在我尝试执行此操作的任何地方,我要么得到相同的错误,要么出现解析错误。

顺便说一下,我对矩阵的定义是

pub struct Matrix<T> {
    pub rows: usize,
    pub cols: usize,
    pub data: Vec<T>,
}

【问题讨论】:

    标签: rust


    【解决方案1】:

    使用T: Add 作为绑定表示可以写T + T,但它对由此产生的类型没有任何限制,特别是它可能不是T。您依靠它是 T 才能返回 Matrix&lt;T&gt;

    一种方法是要求T: Add&lt;Output = T&gt;,以便T + T 返回T

    impl<T: Add<Output = T>> Add for Matrix<T> {
        ...
    }
    

    另一种方法是使用T 想要给出的任何输出:即您的添加将返回Matrix&lt;T::Output&gt;

    impl<T: Add> Add for Matrix<T>
    {
        type Output = Matrix<T::Output>;
    
        fn add(self, _rhs: Matrix<T>) -> Matrix<T::Output>
        {
            assert!(self.rows == _rhs.rows && self.cols == _rhs.cols,
                    "attempting to add matrices of different sizes");
    
            let mut res = Matrix {
                rows: self.rows,
                cols: self.cols,
                data : Vec::with_capacity(self.rows * self.cols),
            };
    
            for i in 0..self.rows*self.cols{
                res.data.push(self.data[i] + _rhs.data[i]);
            }
            res
       }
    }
    

    但是,这两个都遇到了一个问题:

    <anon>:23:27: 23:39 error: cannot move out of indexed content
    <anon>:23             res.data.push(self.data[i] + _rhs.data[i]);
                                        ^~~~~~~~~~~~
    <anon>:23:42: 23:54 error: cannot move out of indexed content
    <anon>:23             res.data.push(self.data[i] + _rhs.data[i]);
                                                       ^~~~~~~~~~~~
    

    Add/+ 运算符拥有其参数的所有权,并且无​​法将所有权移出具有直接索引的向量(通常,编译器无法判断一个人不会尝试访问已移动的-out 索引,稍后,这将是一个安全问题)。幸运的是,有一个解决方案:vectors 支持移出迭代器,可以同步移出self_rhs

    for (a, b) in self.data.into_iter().zip(_rhs.data.into_iter()) {
        res.data.push(a + b)
    }
    

    ab 变量都是 T 类型,即所有权已经转移。


    小注,实际上可以进一步“迭代”代码,写作:

    fn add(self, _rhs: Matrix<T>) -> Matrix<T::Output>
    {
        assert!(self.rows == _rhs.rows && self.cols == _rhs.cols,
                "attempting to add matrices of different sizes");
    
        let data = self.data.into_iter()
             .zip(_rhs.data.into_iter())
            .map(|(a,b)| a + b)
            .collect();
        Matrix {
            rows: self.rows,
            cols: self.cols,
            data: data
        }
    }
    

    【讨论】:

    • 谢谢。我理解需要指出输出类型也是 T,但我显然还没有完全理解所有权。需要更多研究...
    猜你喜欢
    • 2016-06-01
    • 2013-06-25
    • 2019-04-25
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    相关资源
    最近更新 更多