给出以下结构:
struct Vector3D {
x: f32,
y: f32,
z: f32
}
我希望重叠其*
运算符以在右侧为Vector3D
时执行点积,并在RHS为f32
时执行逐元素乘法运算。我的代码如下所示:
// Multiplication with scalar
impl Mul<f32, Vector3D> for Vector3D {
fn mul(&self, f: &f32) -> Vector3D {
Vector3D {x: self.x * *f, y: self.y * *f, z: self.z * *f}
}
}
// Multiplication with vector, aka dot product
impl Mul<Vector3D, f32> for Vector3D {
fn mul(&self, other: &Vector3D) -> f32 {
self.x * other.x + self.y * other.y + self.z * other.z
}
}
编译器说第一个impl块:
Vector3D.rs:40:1: 44:2 error: conflicting implementations for trait `std::ops::Mul`
Vector3D.rs:40 impl Mul<f32, Vector3D> for Vector3D {
...
Vector3D.rs:53:1: 57:2 note: note conflicting implementation here
Vector3D.rs:53 impl Mul<Vector3D, f32> for Vector3D {
...
,反之亦然,其他实施。
答案 0 :(得分:27)
从Rust 1.0开始,您现在可以实现此目的:
use std::ops::Mul;
#[derive(Copy, Clone, PartialEq, Debug)]
struct Vector3D {
x: f32,
y: f32,
z: f32,
}
// Multiplication with scalar
impl Mul<f32> for Vector3D {
type Output = Vector3D;
fn mul(self, f: f32) -> Vector3D {
Vector3D {
x: self.x * f,
y: self.y * f,
z: self.z * f,
}
}
}
// Multiplication with vector, aka dot product
impl Mul<Vector3D> for Vector3D {
type Output = f32;
fn mul(self, other: Vector3D) -> f32 {
self.x * other.x + self.y * other.y + self.z * other.z
}
}
fn main() {
let a = Vector3D {
x: 1.0,
y: 2.0,
z: 3.0,
};
let b = a * -1.0;
let c = a * b;
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
}
允许这一点的重大变化是引入了关联类型,它在每个实现中显示为type Output =
位。另一个值得注意的变化是,运算符traits现在按值使用参数,消耗它们,所以我继续为结构实现Copy
。
答案 1 :(得分:12)
目前每个特质类型对只允许一个impl
。
这种情况将随着RFC 48进行改进,但这不是完整的故事(它不是真正的故事)。相关部分是Coherence,它当然没有具体提到运营商超载情况,并且基本上说它仍然是非法的:
以下示例不正常:
trait Iterator<E> { ... } impl Iterator<char> for ~str { ... } impl Iterator<u8> for ~str { ... }
Niko Matsakis(RFC&amp; Rust类型系统专家的作者)一直在考虑这些超载特征:他是published(“如果我想要超载怎么办?”)的伎俩下面,但他表达了他对此的厌恶,并提到他希望允许实施,因为你已经写了......
...这是RFC 135进入的地方。"multidispatch traits"中详细介绍了这种情况。
您现在可以使用辅助特征来解决它。额外的特征层允许您只编写一个impl Mul<...> for Vector3D
,但代价是需要为您希望多个Mul
实现的每种类型设置一个新特征。
#[deriving(Show)]
struct Vector3D {
x: f32,
y: f32,
z: f32
}
trait MulVec3D<Res> {
fn do_mul(&self, v: &Vector3D) -> Res;
}
// Multiplication with scalar
impl MulVec3D<Vector3D> for f32 {
fn do_mul(&self, v: &Vector3D) -> Vector3D {
Vector3D {x: v.x * *self, y: v.y * *self, z: v.z * *self}
}
}
// Multiplication with vector, aka dot product
impl MulVec3D<f32> for Vector3D {
fn do_mul(&self, v: &Vector3D) -> f32 {
self.x * v.x + self.y * v.y + self.z * v.z
}
}
impl<Res, RHS: MulVec3D<Res>> Mul<RHS, Res> for Vector3D {
fn mul(&self, rhs: &RHS) -> Res {
rhs.do_mul(self)
}
}
fn main() {
let a = Vector3D { x: 1.0, y: 2.0, z: 3.0 };
let b = Vector3D { x: -3.0, y: 2.0, z: -1.0 };
println!("{}, {}", a * 2f32, a * b); // Vector3D { x: 2, y: 4, z: 6 }, -2
}