Как преобразовать изменяемую ссылку на себя в неизменяемую ссылку, которая будет использоваться в качестве аргумента для метода? - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть следующий код, который не может быть скомпилирован:

struct A {
    x: i32,
}

impl A {
    fn add_assign(&mut self, other: &Self) {
        self.x += other.x;
    }

    fn double(&mut self) {
        self.add_assign(self);
    }
}

Ошибка:

error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
  --> src/lib.rs:11:9
   |
11 |         self.add_assign(self);
   |         ^^^^^----------^----^
   |         |    |          |
   |         |    |          immutable borrow occurs here
   |         |    immutable borrow later used by call
   |         mutable borrow occurs here

Как передать self в качестве аргумента add_assign?Я безуспешно пытался &self, *self, &*self.

1 Ответ

0 голосов
/ 06 февраля 2019

Для текущей версии вопроса

fn add_assign(&mut self, other: &Self)

Ваш запрос невозможен.

У вас не может быть изменяемой ссылки и неизменной ссылки на одно и то же значениев то же время.Это фундаментальный аспект Rust.

Пожалуйста, перечитайте Правила ссылок .

См. Также:

Для первая версия вопроса

fn add_assign(&mut self, other: Self)

Ваш запрос невозможен.

Вам нужен один экземпляр struct A для вызова метода и другой экземпляр A для передачи в качестве аргумента.Ваш тип не реализует Copy или Clone и не предоставляет каких-либо эквивалентных методов, поэтому нет способа получить второй экземпляр.

Кроме этого, не существует универсального способа взятьизменяемая ссылка на значение и извлечение из него собственной стоимости.

См. также:

Временные решения

Если вы реализуете Copy или Clone, то вы можете получить второе значение из оригинала и затем вызвать любую из ваших версий.

Если вы реализовали Copy:

  • (other: Self)

    self.add_assign(*self);
    
  • (other: &Self)

    let other = *self;
    self.add_assign(&other);
    

Если только Clone:

  • (other: Self)

    self.add_assign(self.clone());
    
  • (other: &Self)

    self.add_assign(&self.clone());
    

Возможно, вы захотите реализовать черту AddAssign для обеспечения синтаксического сахара.Предполагается, что вы реализовали Copy:

impl A {
    fn double(&mut self) {
        *self += *self;
    }
}

impl std::ops::AddAssign<Self> for A {
    fn add_assign(&mut self, other: Self) {
        self.x += other.x;
    }
}

Комментарий Stargateur также может быть применим, поскольку i32 реализует Copy:

impl A {
    fn double(&mut self) {
        *self += self.x;
    }
}

impl std::ops::AddAssign<i32> for A {
    fn add_assign(&mut self, other: i32) {
        self.x += other;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...