Rust Rc<;特质>;选择<;T>;?

Rust Rc<;特质>;选择<;T>;?,rust,trait-objects,Rust,Trait Objects,我正在尝试实现一个如下所示的方法: fn concretify<T: Any>(rc: Rc<Any>) -> Option<T> { Rc::try_unwrap(rc).ok().and_then(|trait_object| { let b: Box<Any> = unimplemented!(); b.downcast().ok().map(|b| *b) }) } 但是,Rc::in

我正在尝试实现一个如下所示的方法:

fn concretify<T: Any>(rc: Rc<Any>) -> Option<T> {
    Rc::try_unwrap(rc).ok().and_then(|trait_object| {
        let b: Box<Any> = unimplemented!();
        b.downcast().ok().map(|b| *b)
    })
}
但是,
Rc::into_raw()
似乎要求
Rc
中包含的类型大小为
size
,理想情况下,我不希望必须使用
不安全的

有什么方法可以实现这一点吗


,我在这里寻找
rc_to_box
的实现。

如果您希望将原始值移出
rc
,我认为不可能实现您的
具体化
功能;看看原因

如果您愿意返回克隆,很简单:

fn concretify<T: Any+Clone>(rc: Rc<Any>) -> Option<T> {
    rc.downcast_ref().map(Clone::clone)
}
fn具体化(rc:rc


如果您想要更“动态”的东西,并且创建值很便宜,您也可以制作一个虚拟对象,使用
downcast\u mut()
而不是
downcast\u ref()
,然后使用虚拟对象交换
std::mem::swap

不幸的是,
Rc
的API似乎缺少必要的方法,无法在
!size
时获得包装类型的所有权

唯一可以返回
Rc
内部项的方法是
Rc::try_unwrap
,但是它返回
结果
,这要求
T
的大小为
size

为了做你想做的事情,你需要一个带有签名的方法:
Rc->Result
,它允许
T
!调整大小,从那里你可以提取
,并执行
向下转换
调用

然而,由于
Rc
是如何实现的,这种方法是不可能的

struct RcBox<T: ?Sized> {
    strong: Cell<usize>,
    weak: Cell<usize>,
    value: T,
}

pub struct Rc<T: ?Sized> {
    ptr: *mut RcBox<T>,
    _marker: PhantomData<T>,
}

这里有一个不和谐:
选项
拥有
T
,而
Rc
只是对象的共同所有者之一。我可以看到两种处理方法:如果有多个所有者,则返回
,或者将函数从
&Rc
转换为
选项
。第一种方法真的是你想要的吗想要?这就是它的用途--它确保给定的
Rc
是唯一的所有者。“
concretify
”应该返回
None
,如果有多个所有者或者
Any
不是
T
。在这种情况下,只需检查:),你同意
None
吗,还是更愿意返回一个
结果
,在其
Err
字段中指定问题是类型不匹配还是多个所有者?如果我是一个更好的人,我想要
结果
:)如果只有
结果
才可能,我当然会接受这一点,但我相对确定问题的语义是相同的,不管我使用的是
选项
结果
,还是
恐慌!(“坏事情发生了,伙计们”)
是的,这只是一个表面上的改变:)恐怕我不确定链接问题的哪一部分阻止了
框的功能。我正在尝试(此时)将
Rc
转换为
Box
。(编辑问题以澄清这一点)嗯,我总是忘记
任何
文档的一部分在
框下
!说得好,不清楚,现在我不太确定;我等会儿再看看能否改进我的答案。
#[derive(Debug,Clone)]
struct Foo(u32);

#[derive(Debug,Clone)]
struct Bar(i32);

fn main() {
    let rc_foo: Rc<Any> = Rc::new(Foo(42));
    let rc_bar: Rc<Any> = Rc::new(Bar(7));
    
    let foo: Option<Foo> = concretify(rc_foo);
    println!("Got back: {:?}", foo);
    let bar: Option<Foo> = concretify(rc_bar);
    println!("Got back: {:?}", bar);
}
struct RcBox<T: ?Sized> {
    strong: Cell<usize>,
    weak: Cell<usize>,
    value: T,
}

pub struct Rc<T: ?Sized> {
    ptr: *mut RcBox<T>,
    _marker: PhantomData<T>,
}
use std::any::Any;
use std::{cell, mem, ptr};
use std::rc::Rc;

struct RcBox<T: ?Sized> {
    strong: cell::Cell<usize>,
    _weak: cell::Cell<usize>,
    value: T,
}

fn concretify<T: Any>(rc: Rc<Any>) -> Option<T> {
    //  Will be responsible for freeing the memory if there is no other weak
    //  pointer by the end of this function.
    let _guard = Rc::downgrade(&rc);

    unsafe {
        let killer: &RcBox<Any> = {
            let killer: *const RcBox<Any> = mem::transmute(rc);
            &*killer 
        };

        if killer.strong.get() != 1 { return None; }

        //  Do not forget to decrement the count if we do take ownership,
        //  as otherwise memory will not get released.
        let result = killer.value.downcast_ref().map(|r| {
            killer.strong.set(0);
            ptr::read(r as *const T)
        });

        //  Do not forget to destroy the content of the box if we did not
        //  take ownership
        if result.is_none() {
            let _: Rc<Any> = mem::transmute(killer as *const RcBox<Any>);
        }

        result
    }
}

fn main() {
    let x: Rc<Any> = Rc::new(1);
    println!("{:?}", concretify::<i32>(x));
}