2016-05-17 10 views
1

Der folgende Code gibt den Fehler "kann nicht ausgeliehenen Inhalt ausziehen". Ich weiß, dass es hier schon viele Fragen gibt. Ich denke, dass jeder, der Rust benutzt, sich irgendwann hier befindet und versucht herauszufinden, was genau mit dem Besitz geschieht. Ich denke, ich weiß, was hier vor sich geht und wie ich es beheben kann, ich weiß einfach nicht, wie ich in diesem speziellen Fall eine Referenz verwenden soll. Wenn es einen idiomatischen Weg gibt, um das zu erreichen, was ich versuche, lass es mich in den Kommentaren wissen.Referenz auf Parameter innerhalb einer Enum

Ich kann sehen, wo ich versuche, Besitz zu übernehmen, aber ich bin mir nicht sicher, wie man stattdessen eine Referenz verwendet.

Schauen wir uns etwas minimal Beispiel:

/* I define two shape structs. The main point here is that they 
are not default copyable, unlike most primitive types */ 

struct Circle { 
    center_x: f64, 
    center_y: f64, 
    r: f64, 
} 

struct Square { 
    center_x: f64, 
    center_y: f64, 
    length: f64, 
} 

/* this enum will be a container for shapes because we don't know 
    which shape we might need. */ 

enum Shape { 
    // these are scoped differently, so it's okay. 
    Circle(Circle), 
    Square(Square), 
} 

/* I'm making cookies, each cookie has a shape */ 
struct Cookie { 
    shape: Shape, 
} 

/* All of the above was setup, here is where we find errors */ 

impl Cookie { 

    /* checks if two cookies have the same radius. squares -> false */ 

    fn has_same_radius(&self, other_cookie: &Cookie) -> bool { 
    // fn has_same_radius(self, other_cookie: Cookie) -> bool { 

    /* swapping the above two lines will remedy the error, 
     but I don't want this function to take ownership of either */ 

     match self.shape { 

      /* As soon as I declare c1, I'm taking ownership of self.shape 
       and therefore self as well. This is in spite of the fact 
       that I never plan to alter anything. 
       How can I simply use a reference to c1> */ 

      Shape::Circle(c1) => match other_cookie.shape { 

       /* same thing here with c2 */ 
       Shape::Circle(c2) => { 
        if c2.r == c1.r { 
         return true; 
        } 
       } 
       Shape::Square(_) => return false, 

      }, 
      Shape::Square(_) => return false, 
     } 
     return false; 

    } 

} 

Wenn ich auf dem Shape Enum übereinstimmen, ich will nur den Parameter in Shape eingekapselt verweisen, aber da ich bin nicht eine Referenz verwendet wird, versuche ich, Besitz der gesamten Cookie-Struktur übernehmen.

+0

Bitte lesen Sie die Fehlermeldungen des Compilers vollständig durch. Die Nachricht sagt "help: um den Umzug zu verhindern, verwenden Sie' ref c1' oder 'ref mut c1', um den Wert als Referenz zu erfassen". Wenn Sie die Fehlermeldungen zu verwirrend finden, [Datei ein Problem] (https://github.com/rust-lang/rust) beschreibt, welche bessere Formulierung oder Darstellung der Fehler es deutlicher gemacht hätte. – Shepmaster

+1

@Shempmaster Ich habe ungefähr 2 Stunden damit verbracht, das herauszufinden. Ich wusste, dass es etwas Einfaches sein musste, aber als ich 'ref c1 'las, versuchte ich, Rust neu zu sein, sofort' & c1'. Nun, da es erwähnt wurde, erinnere ich mich daran, in der Dokumentation über "ref" zu lesen, als ich es zum ersten Mal durchging, aber ich erinnere mich daran, keinen Kontext zu sehen, in dem es anders war als "&" und es sofort vergessen zu lassen. Dies ist einer der Fälle, in denen ich wirklich nicht die richtige Frage zu stellen wusste. Jetzt, wo es erklärt wurde, trete ich selbst, weil die Fehlermeldung vollkommen hilfreich war, ich war nur dumm. – Liam

Antwort

3

ändern

.... 
Shape::Circle(c1) => ... 
.... 
Shape::Circle(c2) => ... 
.... 

zu

.... 
Shape::Circle(ref c1) => ... 
.... 
Shape::Circle(ref c2) => ... 
.... 

Playground

let ref x = y; ist im Grunde die Muster-Version von let x = &y; entsprechen.

+0

@Liam Haben Sie das Gefühl, dass dieser oder der andere Ihre Frage beantwortet? Wenn ja, könnten Sie eine der Antworten akzeptieren? – WiSaGaN

1

Wie von WiSaGan gezeigt, müssen Sie ref Muster verwenden, um einen Verweis auf den enthaltenen Wert zu erstellen. Sie können auch den Code-Matching für beide Formen simultan vereinfachen:

impl Cookie { 
    fn has_same_radius(&self, other: &Cookie) -> bool { 
     match (&self.shape, &other.shape) { 
      (&Shape::Circle(ref c1), &Shape::Circle(ref c2)) => c1.r == c2.r, 
      _ => false, 
     } 
    } 
}