How to get dereferenced type in metaprogramming

impl<T: Add<Output = T>> Add for &RowMatrix<T> {
    type Output = Result<GetDeReferencedType<Self>>; // GetDeReferencedType<Self> == RowMatrix<T>
    ......

I want to get Self type's deferenced type.

e.g. if Self is type T, I want to get the type of Deref::Output if T implement trait Deref

Do you mean something like this?

impl<T> Add for &RowMatrix<T> 
where
    T: Add<Output = T> + Deref,
{
    type Output = Result<T::Deref>;
    ...
}

Otherwise, if GetDeReferencedType is meant to be something like Box or Vec where you can "instantiate" it to get Box<Self> or Vec<Self> then this is something called a "higher kinded type" and not currently implemented.

You may be able to get something working using Generic Associated Types.

1 Like

Thanks for your help, I know how to implement that.

To be more concise, this is what I want

impl<T: Add<Output = T>> Add for &RowMatrix<T> {
    type Output = Result<<Self as Deref>::Target>;
    .......

That works. Or is it different from what you actually want?

1 Like

Sorry, My poor English makes u all misunderstand.

I just want the deferenced target type of &RowMatrix<T>. I want to implement Add trait for two immutable reference of RowMatrix<T>, so that I can add two matrices by taking the immutable reference &lhs_matrix + &rhs_matrix where lhs_matrix's type and rhs_matrix's type both are RowMatrix<T>. The result of Add op should be type RowMatrix<T>, so I want Add::Output to be type Result<RowMatrix<T>>

The high level abstraction will be:
&RowMatrix<T> + &RowMatrix<T> -> Result<RowMatrix<T>>

Can you modify this example to be what you want, even if it doesn't compile? Or somehow demonstrate how it isn't what you want?

Almost right, but T should not be bounded Copy trait

Here is my implementation:


#[derive(Debug)]
pub struct RowMatrix<T> {
    rows: usize,
    cols: usize,
    data: Vec<Vec<T>>,
}

impl<T> Add for &RowMatrix<T>
where
    for<'a> &'a T: Add<Output = T>,
{
    type Output = Result<<Self as Deref>::Target>;
    fn add(self, rhs: Self) -> Self::Output {
        if self.rows != rhs.rows || self.cols != rhs.cols {
            return Err(Error::DimensionNotMatched);
        }
        let data = self
            .data
            .iter()
            .zip(rhs.data.iter())
            .map(|(lhs, rhs)| {
                lhs.into_iter()
                    .zip(rhs.into_iter())
                    .map(|(le, re)| le + re)
                    .collect()
            })
            .collect();

        Ok(RowMatrix {
            rows: self.rows,
            cols: self.cols,
            data,
        })
    }
}

This is the complete code.