【问题标题】:Wrapping RefCell and Rc in a struct type将 RefCell 和 Rc 包装在结构类型中
【发布时间】:2018-09-07 14:53:58
【问题描述】:

我想要一个结构体,它有一个可写字段,但显式可借用:

struct App<W: Clone<BorrowMut<Write>>> {
    stdout: W,
}

...所以它可以在内部使用它:

impl<W: Clone<BorrowMut<Write>>> App<W> {
    fn hello(&mut self) -> Result<()> {
        Rc::clone(&self.stdout).borrow_mut().write(b"world\n")?;
        Ok(())
    }
}

我尝试将光标传递给它,然后使用它:

let mut cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor };
app.hello().expect("failed to write");

let mut line = String::new();
Rc::clone(&cursor).borrow_mut().read_line(&mut line).unwrap();

锈皮:

error[E0107]: wrong number of type arguments: expected 0, found 1
 --> src/bin/play.rs:6:21
  |
6 | struct App<W: Clone<BorrowMut<Write>>> {
  |                     ^^^^^^^^^^^^^^^^ unexpected type argument

我的最终目标:将stdinstdoutstderr 传递给App 结构。在fn main 中,这些将是真正的标准输入/标准输出/标准错误。在测试中,这些可能是游标。因为我需要在App 之外访问这些(例如在测试中),所以我需要多个所有者(因此是Rc)和运行时可变借用(因此是RefCount)。

我该如何实现?

【问题讨论】:

  • 你的意思是W同时实现了CloneBorrowMut。所以&lt;W: Clone + BorrowMut&lt;Write&gt;&gt;
  • RefCell::borrow_mutBorrowMut 特征无关。

标签: syntax rust traits type-bounds


【解决方案1】:

这不是您将多个约束应用于类型参数的方式。相反,您使用 + 运算符,如下所示:&lt;W: Clone + Write + BorrowMut&gt;

但是,如果你想让BorrowMut 成为RefCell 的抽象,它就行不通了。 RefCellborrow_mut 方法不是任何特征的一部分,因此您需要在数据结构中直接依赖 RefCell

struct App<W: Clone + Write> {
    stdout: Rc<RefCell<W>>,
}

话虽如此,最好不要对结构施加不必要的约束。您实际上可以将它们放在此处,稍后在 impl 上提及它们。

struct App<W> {
    stdout: Rc<RefCell<W>>,
}

为了访问Rc 的内容,您需要使用* 取消引用。这在您的情况下可能有点棘手,因为 implBorrowMut 之间存在一个毯子,这意味着 Rc 有一个 不同 borrow_mut,这是您绝对不想要的。

impl<W: Clone + Write> App<W> {
    fn hello(&mut self) -> Result<()> {
        (*self.stdout).borrow_mut().write(b"world\n")?;
        Ok(())
    }
}

同样,当您使用它时,您需要取消引用 Rc

let cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor.clone() };
app.hello().expect("failed to write");

let mut line = String::new();

let mut cursor = (&*cursor).borrow_mut();
// move to the beginning or else there's nothing to read
cursor.set_position(0);
cursor.read_line(&mut line).unwrap();

println!("result = {:?}", line);

另外,请注意Rc 被克隆到光标中。否则它会被移动,您以后无法再次使用它。

【讨论】:

  • 谢谢,这行得通!我还认为可以从 W 定义中删除 + Clone
猜你喜欢
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多