rust - Mismatched types when implementing a trait -
to learn rust, i'm building own matrix class. implementation of add trait follows:
impl<t: add> add matrix<t> { type output = matrix<t>; fn add(self, _rhs: matrix<t>) -> matrix<t> { assert!(self.rows == _rhs.rows && self.cols == _rhs.cols, "attempting 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), }; in 0..self.rows*self.cols{ res.data.push(self.data[i] + _rhs.data[i]); } res } }
but following error
compiling matrix v0.1.0 (file://~/soft/rust/projects/matrix) src/lib.rs:35:27: 35:54 error: mismatched types: expected `t`, found `<t core::ops::add>::output` (expected type parameter, found associated type) [e0308] src/lib.rs:35 res.data.push(self.data[i] + _rhs.data[i]); ^~~~~~~~~~~~~~~~~~~~~~~~~~~
going error report, guess need indicate somewhere else t implements add trait anywhere try either same error or parsing error.
my definition of matrix way is
pub struct matrix<t> { pub rows: usize, pub cols: usize, pub data: vec<t>, }
using t: add
bound says 1 can write t + t
, doesn't place restriction on type result that, in particular, may not t
. you're relying on being t
able return matrix<t>
.
one approach require t: add<output = t>
, t + t
returns t
:
impl<t: add<output = t>> add matrix<t> { ... }
another approach instead work whatever output t
wants give: i.e. addition return matrix<t::output>
:
impl<t: add> add 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 add matrices of different sizes"); let mut res = matrix { rows: self.rows, cols: self.cols, data : vec::with_capacity(self.rows * self.cols), }; in 0..self.rows*self.cols{ res.data.push(self.data[i] + _rhs.data[i]); } res } }
however, both of these meet problem:
<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
/the +
operator takes ownership of arguments, , 1 cannot move ownership out of vector direct indexing (in general, compiler can't tell 1 won't try access moved-out index again, later, safety problem). fortunately, there's solution: vectors support moving-out iterator, , 1 can walk on self
, _rhs
moving out in lock-step:
for (a, b) in self.data.into_iter().zip(_rhs.data.into_iter()) { res.data.push(a + b) }
the a
, b
variables both of type t
, i.e. ownership has moved.
minor note, 1 can "iteratorise" code more, writing:
fn add(self, _rhs: matrix<t>) -> matrix<t::output> { assert!(self.rows == _rhs.rows && self.cols == _rhs.cols, "attempting add matrices of different sizes"); let data = self.data.into_iter() .zip(_rhs.data.into_iter()) .map(|(a,b)| + b) .collect(); matrix { rows: self.rows, cols: self.cols, data: data } }
Comments
Post a Comment