2016-06-05 4 views
4

Ich lerne Rust, habe die Rust-Homepage gelesen und probiere kleine Beispielprogramme aus. Hier ist Code, der fehlschlägt:Nicht übereinstimmende Typen bei der Rückgabe des Ergebnisses von zwei Generika

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

Hier wird die Fehlermeldung:

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} 
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Ich verstehe nicht, warum es zu kompilieren schlägt fehl.

Antwort

0

Sie müssen den Ausgangstyp Add für T angeben:

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

Ihre Implementierung von add ein Complex<<T as core::ops::Add>::Output> erzeugt. <T as core::ops::Add>::Output (d. H. Die Output der Implementierung von Add<T> für T) ist nicht garantiert dasselbe wie T zu sein. Sie können eine Einschränkung für die Output zugehörigen Typ fügen Sie Ihre Implementierung zu beschränken nur verfügbar sein, wenn sie in der Tat sind die gleichen:

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

Oder Sie könnten Ihre Implementierung verändern so allgemein wie möglich zu sein, indem es möglich gemacht um eine Complex<T> und eine Complex<U> hinzuzufügen, vorausgesetzt, dass es möglich ist, eine T und eine U hinzuzufügen, und indem man eine Complex<<T as Add<U>>::Output> zurückgibt.

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 } 
    } 
} 
+0

Vielen Dank für Ihre Antwort. Das hilft. – Thorum357

5

The Add trait ist definiert als

pub trait Add<RHS = Self> { 
    type Output; 
    fn add(self, rhs: RHS) -> Self::Output; 
} 

heißt, daß (das Merkmal für implementiert Typen) einen Typen für Self gegeben wird, und einen Typ für die rechte Handseite (RHS, die Sache wird hinzugefügt), wird es einen einzigartigen Typ geben, der produziert wird: Output.

Konzeptionell dies ermöglicht es Ihnen, einen Typ zu erstellen A, die einen Typ B hinzugefügt, um es haben kann, die immer einen dritten Typ C produzieren wird.

In Ihrem Beispiel haben Sie T eingeschränkt, um Add zu implementieren. Standardmäßig wird angenommen, dass der Typ RHS dem Typ entspricht, für den das Merkmal implementiert ist (RHS = Self). Es gibt jedoch keine Einschränkungen, was der Ausgabetyp sein muss.

Es gibt zwei mögliche Lösungen:

  1. Sagen Sie, dass Sie eine Complex zurückkehren wird, die durch was auch immer das Ergebnis Typ parametriert wurde T der Zugabe ist:

    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} 
        } 
    } 
    
  2. einschränken T denen Typen, die, wenn sie sich selbst hinzugefügt werden, den gleichen Typ zurückgeben:

    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} 
        } 
    } 
    
Verwandte Themen