我有一个带有两个通用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!()
}
}
答案 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)
}
}
这样我们就可以比较N
和M
。如果它们相等,那么额外的类型参数将是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!()
}
}