如何从Rc <refcell <a >>获取&A参考?

时间:2018-09-01 00:44:20

标签: reference rust smart-pointers borrowing

我有一个我想用安全的Rust解决的设计问题,但我找不到可行的解决方案。我不能使用RefCell,因为您无法获得对数据的&引用,只能是Ref / RefMut

这里是simplified example with irrelevant fields / methods removed

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 :(得分:3)

如果函数的参数类型为var content = marker[3] + marker[9] + marker[8]; ,则可以使用对任何取消引用&A的类型的引用来调用它,其中包括A之类的东西。 Deref特征捕获了一种引用另一种类型的概念。这也是为什么可以使用&Ref<A>&str)调用接受&String的函数的原因。

因此,如果将String: Deref<Target = str>保留为a,则可以很容易地修改代码,如下所示:

Rc<RefCell<A>>

请注意,此方法先取消引用library_struct.function(&*self.a.borrow()); ,然后重新借用,以便可以将其强制为特征对象。