地图从Rc<RefCell<T>>到Ref<'_,U&gt。

问题描述 投票:1回答:1

我有以下结构。

struct Inner;

enum State {
    A(Inner),
    B,
}

struct Owner {
    state: Rc<RefCell<State>>,
}

我想提供以下接口。

impl Owner {
    fn a(&self) -> Option<Ref<'_, Inner>>;
}

其中 owner.a() 会回来的。

  • 当... 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),
            _ => {}
        }
    }
}

游戏场

rust borrow-checker borrowing
1个回答
2
投票

owner.a() 不需要增加 Rc的强数,因为返回的 Ref'的一生已经与 Rc. 如果你使用的是100%安全的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!(),
            })),
        }
    }
}

playground

© www.soinside.com 2019 - 2024. All rights reserved.