2016-05-17 2 views
1

В приведенном ниже коде приведена ошибка «не может выйти из заимствованного контента». Я знаю, что здесь уже много вопросов об этом. Я думаю, что каждый, кто использует Ржавчу, оказывается здесь в какой-то момент, пытаясь выяснить, что происходит с владением. Я думаю, что я знаю, что здесь происходит и как это исправить, я просто не знаю, как использовать ссылку в этом конкретном случае. Если есть более идиоматический способ выполнить то, что я пытаюсь, пожалуйста, дайте мне знать в комментариях.Ссылка на параметры в перечислении

Я вижу, где я пытаюсь взять на себя ответственность, но я не уверен, как использовать ссылку.

Давайте посмотрим на несколько минимальный пример:

/* 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; 

    } 

} 

Когда я сопрягать на Shape перечислении, я только хочу, чтобы ссылаться на параметр инкапсулированный в Shape, но так как я не использую ссылку, я пытаюсь чтобы взять на себя ответственность за всю структуру Cookie.

+0

Пожалуйста, полностью прочитайте сообщения об ошибках, которые предоставляет компилятор. В сообщении говорится: «Помогите: чтобы предотвратить перемещение, используйте' ref c1' или 'ref mut c1' для захвата значения по ссылке». Если вы обнаружите, что сообщения об ошибках слишком сбивают с толку, тогда [указать проблему] (https://github.com/rust-lang/rust), описывая, что лучше формулировать или представлять ошибки, стало бы более ясным. – Shepmaster

+1

@Shepmaster Я потратил около 2 часов, пытаясь понять это. Я знал, что это должно быть что-то простое, но когда я читаю 'ref c1', я, будучи новым для Rust, сразу же попробовал' & c1'. Теперь, когда это было упомянуто, я действительно помню, как читал о 'ref' в документации, когда я впервые проходил его, но я не помню, чтобы не было никакого контекста, где он отличался от' & 'и быстро выводил его из головы. Это один из тех случаев, когда я действительно даже не знал правильного вопроса. Теперь, когда его объяснили, я пинаю себя, потому что сообщение об ошибке было очень полезно, я просто был немым. – Liam

ответ

3

Изменить

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

в

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

Playground

let ref x = y; в основном шаблон соответствия версии let x = &y;.

+0

@ Liam Вы чувствуете, что тот или другой ответили на ваш вопрос? Если да, можете ли вы принять один ответ? – WiSaGaN

1

Как указано WiSaGan, вы должны использовать шаблон ref, чтобы создать ссылку на содержащееся значение. Вы также можете упростить сопоставление кода с двумя формами одновременно:

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, 
     } 
    } 
} 
Смежные вопросы