在结构类型中包装RefCell和Rc

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

我想有一个具有可写字段但明确可借用的结构:

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中,这些将是真正的stdin / stdout / stderr。在测试中,这些可能是游标。由于我需要在App之外访问这些(例如在测试中),我需要多个所有者(因此Rc)和运行时可变借用(因此RefCount)。

我该如何实现呢?

syntax rust traits type-bounds
1个回答
2
投票

这不是您如何将多个约束应用于类型参数。相反,你使用+运算符,如下所示:<W: Clone + Write + BorrowMut>

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

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

话虽如此,最好不要在结构上放置不必要的约束。你可以把它们留在这里,稍后再在impl上提及它们。

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

要访问Rc的内容,您需要使用*取消引用。这在你的情况下可能有点棘手,因为有一个impl的毯子BorrowMut,这意味着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被克隆到光标中。否则它将被移动,你以后不能再使用它。

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