我正在学习 Rust,已经阅读了 Rust 主页,并且正在尝试一些小的示例程序。下面是失败的代码:
use std::ops::Add;
pub struct Complex<T> {
pub re: T,
pub im: T,
}
impl <T: Add> Add<Complex<T>> for Complex<T> {
type Output = Complex<T>;
fn add(self, other: Complex<T>) -> Complex<T> {
Complex {re: self.re + other.re, im: self.im + other.im}
}
}
以下是错误消息:
src/lib.rs:11:3: 11:59 error: mismatched types:
expected `Complex<T>`,
found `Complex<<T as core::ops::Add>::Output>`
(expected type parameter,
found associated type) [E0308]
src/lib.rs:11 Complex {re: self.re + other.re, im: self.im + other.im}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我不明白为什么它无法编译。
Add
特征定义为
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
也就是说,给定一个用于Self
的类型(实现特征的类型)和一个用于右侧的类型(RHS
,要添加的东西),将产生一个唯一的类型:Output
。
从概念上讲,这允许您创建一个类型A
,该类型可以向其添加B
类型,这将始终生成第三个类型C
。
在您的示例中,您限制了T
实现Add
。默认情况下,假定RHS
类型与为其实现特征的类型相同 (RHS = Self
)。但是,对输出类型必须是什么没有任何限制。
有两种可能的解决方案:
假设您将返回一个已由添加
T
的结果类型参数化的Complex
:impl<T> Add<Complex<T>> for Complex<T> where T: Add, { type Output = Complex<T::Output>; fn add(self, other: Complex<T>) -> Complex<T::Output> { Complex { re: self.re + other.re, im: self.im + other.im, } } }
将
T
限制为那些在添加到自身时返回相同类型的类型:impl<T> Add<Complex<T>> for Complex<T> where T: Add<Output = T>, { type Output = Complex<T>; fn add(self, other: Complex<T>) -> Complex<T> { Complex { re: self.re + other.re, im: self.im + other.im, } } }
另请参阅:
- 如何要求泛型类型在泛型函数中实现 Add、Sub、Mul 或 Div 等操作?
- 如何编写用于添加两个泛型类型的引用的 Trait 绑定?
您对add
的实现会产生一个Complex<<T as core::ops::Add>::Output>
。<T as core::ops::Add>::Output
(即T
实施Add<T>
Output
)不保证与T
相同。可以在Output
关联类型上添加约束,以将实现限制为仅在它们实际上相同时才可用:
impl<T: Add<Output = T>> Add for Complex<T> {
type Output = Complex<T>;
fn add(self, other: Complex<T>) -> Complex<T> {
Complex { re: self.re + other.re, im: self.im + other.im }
}
}
或者,你可以通过添加Complex<T>
和Complex<U>
来更改你的实现,尽可能通用,前提是可以添加一个T
和一个U
,并返回一个Complex<<T as Add<U>>::Output>
。
impl<T: Add<U>, U> Add<Complex<U>> for Complex<T> {
type Output = Complex<<T as Add<U>>::Output>;
fn add(self, other: Complex<U>) -> Self::Output {
Complex { re: self.re + other.re, im: self.im + other.im }
}
}
您需要为T
指定Add
的输出类型:
impl <T: Add<Output = T>> Add for Complex<T> {
type Output = Complex<T>;
fn add(self, other: Complex<T>) -> Complex<T> {
Complex {re: self.re + other.re, im: self.im + other.im}
}
}