gpt4 book ai didi

rust - 如何将 Rc>> 传递给接受 Rc>> 的函数?

转载 作者:行者123 更新时间:2023-11-29 07:55:26 27 4
gpt4 key购买 nike

我最初问过这个问题 here , 但它被标记为重复,尽管在我看来它只复制了一部分,所以我创建了一个更具体的:

考虑以下代码:

use std::rc::Rc;

trait MyTrait {
fn trait_func(&self);
}

struct MyStruct1;

impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}

impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}

fn my_trait_fn(t: Rc<dyn MyTrait>) {
t.trait_func();
}

fn main() {
let my_str: Rc<MyStruct1> = Rc::new(MyStruct1);
my_trait_fn(my_str.clone());
my_str.my_fn();
}

这段代码工作正常。现在我想更改 trait_func 的定义以接受 &mut self,但它不会起作用,因为 Rc 仅适用于不可变数据。我使用的解决方案是将 MyTrait 包装到 RefCell 中:

use std::cell::RefCell;

fn my_trait_fn(t: Rc<RefCell<Box<dyn MyTrait>>>) {
t.borrow_mut().trait_func();
}

fn main() {
let my_str: Rc<RefCell<Box<MyStruct1>>> = Rc::new(RefCell::new(Box::new(MyStruct1)));
my_trait_fn(my_str.clone());
my_str.my_fn();
}

编译时出现错误:

error[E0308]: mismatched types
--> src/main.rs:27:17
|
27 | my_trait_fn(my_str.clone());
| ^^^^^^^^^^^^^^ expected trait MyTrait, found struct `MyStruct1`
|
= note: expected type `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn MyTrait + 'static>>>`
found type `std::rc::Rc<std::cell::RefCell<std::boxed::Box<MyStruct1>>>`
= help: here are some functions which might fulfill your needs:
- .into_inner()

解决这个问题的最佳方法是什么?

最佳答案

(这个答案的旧版本基本上建议克隆底层结构并将其放入新的 Rc<RefCell<Box<MyTrait>> 对象中;这在稳定的 Rust 上是必要的,但因为在那之后不久,Rc<RefCell<MyStruct>> 将强制到 Rc<RefCell<MyTrait>> 没有问题。)

去掉 Box<> 包装,你就可以自由轻松地将 Rc<RefCell<MyStruct>> 强制转换为 Rc<RefCell<MyTrait>>。回想一下克隆一个 Rc<T> 只会产生另一个 Rc<T> ,将引用计数增加一个,你可以这样做:

use std::rc::Rc;
use std::cell::RefCell;

trait MyTrait {
fn trait_func(&self);
}

#[derive(Clone)]
struct MyStruct1;
impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}

impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}

fn my_trait_fn(t: Rc<RefCell<MyTrait>>) {
t.borrow_mut().trait_func();
}

fn main() {
// (The type annotation is not necessary here, but helps explain it.
// If the `my_str.borrow().my_fn()` line was missing, it would actually
// be of type Rc<RefCell<MyTrait>> instead of Rc<RefCell<MyStruct1>>,
// essentially doing the coercion one step earlier.)
let my_str: Rc<RefCell<MyStruct1>> = Rc::new(RefCell::new(MyStruct1));
my_trait_fn(my_str.clone());
my_str.borrow().my_fn();
}

作为一般规则,看看你是否可以让事物通过引用获取包含的值,理想情况下甚至是通用的——fn my_trait_fn<T: MyTrait>(t: &T) 和类似的,通常可以称为 my_str.borrow(),自动引用和取消引用处理其余部分——而不是整个 Rc<RefCell<MyTrait>> 东西。

关于rust - 如何将 Rc<RefCell<Box<MyStruct>>> 传递给接受 Rc<RefCell<Box<dyn MyTrait>>> 的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30861295/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com