当类型参数相同时,使用不同的impl

时间:2017-03-25 19:58:07

标签: rust typenum

我有一个带有两个通用typenum参数的impl。当参数相同时,impl的函数应返回不同的类型。 (不同的类型是一种更紧凑的表示,只有在类型参数相同时才能实现。)是否可以根据类型相等使用不同的impl?下面的天真方法会产生“冲突实现”错误,因为Rust没有采取更具体的实现。

extern crate typenum;
use typenum::Unsigned;

use std::ops::Mul;
use std::marker::PhantomData;

struct Matrix<N: Unsigned, M: Unsigned> {
    n: usize,
    m: usize,
    elements: Vec<f64>,
    _marker: PhantomData<(N, M)>
}

// The more compact representation
struct SquareMatrix<N: Unsigned> {
    n: usize,
    elements: Vec<f64>,
    _marker: PhantomData<(N)>
}

impl<N: Unsigned, D: Unsigned, M: Unsigned> Mul<Matrix<D, M>> for Matrix<N, D> {
    type Output = Matrix<N, M>;
    fn mul(self, rhs: Matrix<D, M>) -> Self::Output {
        unimplemented!()
    }
}

// The more specific implementation
impl<N: Unsigned, D: Unsigned> Mul<Matrix<D, N>> for Matrix<N, D> {
    type Output = SquareMatrix<N>;
    fn mul(self, rhs: Matrix<D, N>) -> Self::Output {
        unimplemented!()
    }
}

2 个答案:

答案 0 :(得分:2)

使用specialization(从Rust 1.16.0开始仍然不稳定),你可以。基本上,您只需要使用default在更一般的实现中声明项目来说明&#34;这可以是专门的&#34;。

#![feature(specialization)]

impl<N: Unsigned, D: Unsigned, M: Unsigned> Mul<Matrix<D, M>> for Matrix<N, D> {
    default type Output = Matrix<N, M>;

    default fn mul(self, rhs: Matrix<D, M>) -> Self::Output {
        unimplemented!()
    }
}

// The more specific implementation
impl<N: Unsigned, D: Unsigned> Mul<Matrix<D, N>> for Matrix<N, D> {
    type Output = SquareMatrix<N>;

    fn mul(self, rhs: Matrix<D, N>) -> Self::Output {
        unimplemented!()
    }
}

答案 1 :(得分:2)

你现在可以在稳定的Rust中做到这一点,它只需要一些额外的锅炉板。

首先,我们将创建一个内部乘法特征来完成实际工作:

pub trait MulPrivate<Rhs, AreEqual> {
    type Output;
    fn mul_private(self, rhs: Rhs) -> Self::Output;
}

注意额外的类型参数:这是我们区分这两种情况的方式。

然后,我们定期Mul实施调用此内部调用:

use typenum::{IsEqual, Eq};
impl<N, M, D> Mul<Matrix<D, M>> for Matrix<N, D>
    where D: Unsigned,
          M: Unsigned,
          N: Unsigned + IsEqual<M>,
          Matrix<N, D>: MulPrivate<Matrix<D, M>, Eq<N, M>>,
{
    type Output = <Matrix<N, D> as MulPrivate<Matrix<D, M>, Eq<N, M>>>::Output;
    fn mul(self, rhs: Matrix<D, M>) -> Self::Output {
        self.mul_private(rhs)
    }
}

这样我们就可以比较NM。如果它们相等,那么额外的类型参数将是True,否则它将是False。现在我们可以自由地进行MulPrivate的两种不同实现:

use typenum::{True, False};
impl<N: Unsigned, D: Unsigned, M: Unsigned> MulPrivate<Matrix<D, M>, False> for Matrix<N, D> {
    type Output = Matrix<N, M>;
    fn mul_private(self, rhs: Matrix<D, M>) -> Self::Output {
        println!("not square!");
        unimplemented!()
    }
}

// The more specific implementation
impl<N: Unsigned, D: Unsigned> MulPrivate<Matrix<D, N>, True> for Matrix<N, D> {
    type Output = SquareMatrix<N>;
    fn mul_private(self, rhs: Matrix<D, N>) -> Self::Output {
        println!("square!");
        unimplemented!()
    }
}

请注意,解析this issue后,您将能够删除所有此样的样板并将其写为:

impl<N: Unsigned, D: Unsigned, M: Unsigned> Mul<Matrix<D, M>> for Matrix<N, D> where N: IsEqual<M, Output = False> {
    type Output = Matrix<N, M>;
    fn mul(self, rhs: Matrix<D, M>) -> Self::Output {
        unimplemented!()
    }
}

// The more specific implementation
impl<N: Unsigned, D: Unsigned> Mul<Matrix<D, N>> for Matrix<N, D> where N: IsEqual<N, Output = True>  {
    type Output = SquareMatrix<N>;
    fn mul(self, rhs: Matrix<D, N>) -> Self::Output {
        unimplemented!()
    }
}