从 Rc<RefCell<T>> 映射到 Ref<'_, U>
Map from Rc<RefCell<T>> to Ref<'_, U>
我有以下结构:
struct Inner;
enum State {
A(Inner),
B,
}
struct Owner {
state: Rc<RefCell<State>>,
}
我想提供以下界面:
impl Owner {
fn a(&self) -> Option<Ref<'_, Inner>>;
}
其中 owner.a()
会 return:
- 当
owner.state
匹配State::A(s)
时,然后Some([some ref to s])
(增加owner.state
的强计数并在删除时减少它,同时保证RefCell
借用属性);
- 否则,
None
.
这可能吗?我试过查看 Ref::map
但我似乎无法使其与 Rc<RefCell<_>>
和 Option
.
一起使用
我现在正在做的解决方法是:
impl Owner {
fn with_a(&self, mut callback: impl FnMut(&Inner)) {
match *self.state.borrow() {
State::A(ref inner) => callback(inner),
_ => {}
}
}
}
owner.a()
不需要增加 Rc
的强计数,因为返回的 Ref
的生命周期已经绑定到 Rc
。如果您使用的是 100% Safe Rust 并且它可以编译,您将不会遇到任何内存安全问题,因此您不必担心手动簿记,例如显式递增或递减 Rc
的强计数。 Rc
甚至没有公开更改强计数的方法,这是有充分理由的。这是您想要的函数签名的实现:
use std::rc::Rc;
use std::cell::{RefCell, Ref};
struct Inner;
enum State {
A(Inner),
B,
}
struct Owner {
state: Rc<RefCell<State>>,
}
impl Owner {
fn a(&self) -> Option<Ref<'_, Inner>> {
let state_ref = self.state.borrow();
match *state_ref {
State::B => None,
_ => Some(Ref::map(state_ref, |state| match state {
State::A(inner) => inner,
_ => unreachable!(),
})),
}
}
}
我有以下结构:
struct Inner;
enum State {
A(Inner),
B,
}
struct Owner {
state: Rc<RefCell<State>>,
}
我想提供以下界面:
impl Owner {
fn a(&self) -> Option<Ref<'_, Inner>>;
}
其中 owner.a()
会 return:
- 当
owner.state
匹配State::A(s)
时,然后Some([some ref to s])
(增加owner.state
的强计数并在删除时减少它,同时保证RefCell
借用属性); - 否则,
None
.
这可能吗?我试过查看 Ref::map
但我似乎无法使其与 Rc<RefCell<_>>
和 Option
.
我现在正在做的解决方法是:
impl Owner {
fn with_a(&self, mut callback: impl FnMut(&Inner)) {
match *self.state.borrow() {
State::A(ref inner) => callback(inner),
_ => {}
}
}
}
owner.a()
不需要增加 Rc
的强计数,因为返回的 Ref
的生命周期已经绑定到 Rc
。如果您使用的是 100% Safe Rust 并且它可以编译,您将不会遇到任何内存安全问题,因此您不必担心手动簿记,例如显式递增或递减 Rc
的强计数。 Rc
甚至没有公开更改强计数的方法,这是有充分理由的。这是您想要的函数签名的实现:
use std::rc::Rc;
use std::cell::{RefCell, Ref};
struct Inner;
enum State {
A(Inner),
B,
}
struct Owner {
state: Rc<RefCell<State>>,
}
impl Owner {
fn a(&self) -> Option<Ref<'_, Inner>> {
let state_ref = self.state.borrow();
match *state_ref {
State::B => None,
_ => Some(Ref::map(state_ref, |state| match state {
State::A(inner) => inner,
_ => unreachable!(),
})),
}
}
}