2014-07-06 3 views
16

को देखते हुए निम्नलिखित struct:विभिन्न आरएचएस प्रकारों और मूल्यों को वापस करने के लिए ऑपरेटर को ओवरलोड किया जा सकता है?

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

मैं अपने * ऑपरेटर को ओवरलोड एक डॉट उत्पाद करने के लिए जब दाहिने हाथ की ओर एक Vector3D है, और जब आरएचएस एक 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

यह http://stackoverflow.com/questions/24554738/rust-resolving-trait-impl-conflicts का डुप्लिकेट है। –

+0

@ChrisMorgan यह वास्तव में एक डुप्लिकेट नहीं है। इस प्रश्न में दो ठोस 'इम्प्ल' हैं, जबकि उस प्रश्न में एक ठोस 'इम्प्ल' है जो ठोस के साथ है। – huon

उत्तर

11

इस समय केवल एक ही impl प्रति विशेषता प्रकार जोड़ी की अनुमति है।

यह स्थिति RFC 48 साथ सुधार हो जाएगा, लेकिन यह पूरी कहानी (यह वास्तव में किसी भी कहानी का नहीं है) नहीं है। प्रासंगिक अनुभाग Coherence है, और यह निश्चित रूप से विशेष रूप से ऑपरेटर ओवरलोडिंग मामले का उल्लेख नहीं है, और अनिवार्य रूप से यह अभी भी गैर-कानूनी है का कहना है:

निम्न उदाहरण ठीक नहीं है:

trait Iterator<E> { ... } 
impl Iterator<char> for ~str { ... } 
impl Iterator<u8> for ~str { ... } 

निको मत्साकिस (उस आरएफसी & रास्ट-टाइप-सिस्टम विशेषज्ञ) के लेखक विशेष रूप से इन ओवरलोडिंग विशेषताओं के बारे में सोच रहे हैं: वह वह है जो 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 
} 
+0

यह समाधान पुराना प्रतीत होता है और संकलक त्रुटियों को देता है। Shepmaster का जवाब बिल फिट करने लगता है। – progician

25

जंग 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 = बिट के रूप में दिखाई देता है । एक और उल्लेखनीय परिवर्तन यह है कि ऑपरेटर लक्षण अब मूल्य के आधार पर तर्क लेते हैं, इसलिए मैं आगे बढ़ता हूं और संरचना के लिए Copy लागू करता हूं।

संबंधित मुद्दे

 संबंधित मुद्दे