【问题标题】:How can I obtain an &A reference from a Rc<RefCell<A>>?如何从 Rc<RefCell<A>> 获取 &A 引用?
【发布时间】:2018-09-01 00:44:19
【问题描述】:

我有一个设计问题,我想用安全的 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&lt;RefCell&lt;A&gt;&gt; 解决这个问题,但我被限制在需要&amp;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`

【问题讨论】:

  • 我试图模糊 C 的字段类型,因为它不能是 &amp;'a A。结构 B 和 C 在 Container 中同时存在,并且存在可变性问题,因为 C 中存在不可变引用,而 B 有时需要可变性。
  • 好的,理想情况下,您希望Ca 成为RefCell,但这不适用于库函数?
  • 是的,因为您不能仅从 RefCell 获得 &A Ref / RefMut
  • 我刚刚做了一些更改,我认为这可以传达您的意思。我认为答案是只需Rc&lt;RefCell&lt;A&gt;&gt;,然后将其传递给库函数library_struct.function(&amp;self.a.borrow());
  • 这是可行的,因为Ref 都实现了Deref。如果函数接受&amp;-reference,那么您可以将引用传递给实现Deref 的任何类型,如this example

标签: reference rust smart-pointers borrowing


【解决方案1】:

如果一个函数有一个类型为&amp;A 的参数,那么您可以引用任何取消引用A 的类型来调用它,其中包括&amp;Ref&lt;A&gt; 之类的东西。 Deref 特征捕获了一种类型对另一种类型的解引用的概念。这也是接受&amp;str的函数可以用&amp;StringString: Deref&lt;Target = str&gt;)调用的原因。

因此,如果您将a 保留为Rc&lt;RefCell&lt;A&gt;&gt;,您可以像这样轻松地修复您的代码:

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

请注意,这会取消引用A,然后重新借用它,以便可以将其强制转换为特征对象。

【讨论】:

    猜你喜欢
    • 2021-04-06
    • 1970-01-01
    • 2014-05-23
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 2023-01-20
    • 1970-01-01
    相关资源
    最近更新 更多