Как я могу получить ссылку & A от Rc <RefCell <A>>? - PullRequest
0 голосов
/ 01 сентября 2018

У меня есть проблема с дизайном, которую я хотел бы решить с помощью безопасного Rust, и я не смог найти жизнеспособного решения. Я не могу использовать RefCell, потому что вы не можете получить & ссылку на данные, только Ref / RefMut.

Вот упрощенный пример с удаленными нерелевантными полями / методами

use std::cell::RefCell;
use std::rc::Rc;

struct LibraryStruct {}
impl LibraryStruct {
    fn function(&self, _a: &TraitFromLibrary) {}
}

trait TraitFromLibrary {
    fn trait_function(&self, library_struct: LibraryStruct);
}

// I don't want to copy this, bad performance
struct A {
    // fields...
}

impl TraitFromLibrary for A {
    fn trait_function(&self, library_struct: LibraryStruct) {
        // custom A stuff
    }
}

// B manipulates A's in data
struct B {
    data: Vec<A>,
}

struct C {
    // This type doesn't have to be & for solution. C just needs immutable access
    a: Rc<RefCell<A>>,
}

impl<'a> TraitFromLibrary for C {
    fn trait_function(&self, library_struct: LibraryStruct) {
        // custom C stuff

        // Takes generic reference &, this is why Ref / RefCell doesn't work
        library_struct.function(&self.a.borrow());
    }
}

// B and C's constructed in Container and lifetime matches Container
// Container manipulates fields b and c
struct Container {
    b: B,
    c: Vec<C>,
}

fn main() {}

Я мог бы решить эту проблему с помощью Rc<RefCell<A>>, но меня ограничивают библиотеки, требующие &A.

Это приводит к ошибке:

error[E0277]: the trait bound `std::cell::Ref<'_, A>: TraitFromLibrary` is not satisfied
  --> src/main.rs:33:33
   |
33 |         library_struct.function(&self.a.borrow());
   |                                 ^^^^^^^^^^^^^^^^ the trait `TraitFromLibrary` is not implemented for `std::cell::Ref<'_, A>`
   |
   = note: required for the cast to the object type `TraitFromLibrary`

1 Ответ

0 голосов
/ 01 сентября 2018

Если у функции есть аргумент типа &A, вы можете вызвать его со ссылкой на любой тип, который обращается к A, включая такие вещи, как &Ref<A>. Понятие разыменования одного типа на другое охвачено чертой Deref. Это также причина, по которой функцию, которая принимает &str, можно вызывать с &String (String: Deref<Target = str>).

Итак, если вы сохраните a как Rc<RefCell<A>>, вы можете легко исправить свой код, например:

library_struct.function(&*self.a.borrow());

Обратите внимание, что это разыменовывает A, а затем перезагружает , чтобы его можно было привести к объекту черты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...