微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在转换为 trait 对象时使用 Rc::clone?

如何解决如何在转换为 trait 对象时使用 Rc::clone?

Rust 书说使用 Rc::clone(&x) 而不是 x.clone()Rc 值是惯用的,所以很明显这不是典型的 clone。我完全赞成,但我在实践中无法应用该理论。

我想克隆一个引用计数结构,但将克隆转换为一个特征对象。我可以使用 rc.clone() 执行此操作,但使用 Rc::clone(&rc) 不能。这对我来说……很奇怪。

struct ListView {}
trait View {}
impl View for ListView {}

fn very_contrived_example() {
    let list_view: Rc<ListView> = Rc::new(ListView {});
    let mut views: Vec<Rc<dyn View>> = Vec::new();

    // Using Rc::clone does not work:

    // error[E0308]: mismatched types
    //
    // views.push(Rc::clone(&list_view));
    //                      ^^^^^^^^^^ expected trait object `dyn View`,found struct `ListView`
    //
    // note: expected reference `&Rc<dyn View>`
    //          found reference `&Rc<ListView>`

    // Using a cast works in this very contrived example,but has the
    // disadvantage of moving `list_view`,for some reason,which is not
    // acceptable in general:
    // views.push(Rc::clone(&(list_view as Rc<dyn View>)));

    // But invoking it using method Syntax works fine,without a move:
    views.push(list_view.clone());
}

Rc::clone(&x)x.clone() 有什么区别? x.clone() 实际调用的是什么函数self 的类型是什么?可以直接调用吗?

写这个的惯用方式是什么?

解决方法

这是一种罕见的类型推断失败。显式传递正确的显式类型有效:

views.push(Rc::<ListView>::clone(&list_view))

问题是 Rc::clone(&list_view) 根据 预期类型(即 T)推断 Rc<T> 中的 Rc<dyn View>,而不是基于参数类型。另一方面,当您调用 list_view.clone() 时,它在 Clone 的类型上使用 list_view 的实现,因此它解析为 Rc::<ListView>::clone


如果上面的问题在你的代码中经常出现,并且你想在正常克隆和引用计数的浅克隆之间保持视觉上的区别,你可以写一个小助手特征:

trait RcClone : Clone {
    fn rc_clone(&self) -> Self {
        self.clone()
    }
}

impl<T: ?Sized> RcClone for Rc<T> { }
impl<T: ?Sized> RcClone for Arc<T> { }

然后您可以在代码库中编写 list_view.rc_clone(),它仅适用于引用计数类型。这仍然表明语义与常规克隆不同,但不存在类型推断问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。