Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
723 views
in Technique[技术] by (71.8m points)

rust - How can an operator be overloaded for different RHS types and return values?

Given the following struct:

struct Vector3D {
    x: f32,
    y: f32,
    z: f32
}

I want to overload its * operator to do a dot product when the right hand side is a Vector3D, and to do an element-wise multiplication when the RHS is a f32. My code looks like this:

// 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
    }   
}

The compiler says for the first impl block:

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 { 
...

and vice versa for the other implementation.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As of Rust 1.0, you can now implement this:

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);
}

The big change that allows this is the introduction of associated types, which shows up as the type Output = bit in each implementation. Another notable change is that the operator traits now take arguments by value, consuming them, so I went ahead and implemented Copy for the struct.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...