Generics 如何在堆上构造动态大小的对象

Generics 如何在堆上构造动态大小的对象,generics,rust,Generics,Rust,给定一个包含dyn Trait对象的Box,有没有办法构造一个Boxed非大小化类型 例如,假设我有一个(可能)未调整大小的类型: pub结构IdAndData{ id:i32, 数据:T, } 是否有实现此签名的函数 pub-fn-construct\u from\u-box(id:i32,data:box)->box{ 待办事项!() } 这将允许如下操作: fn main(){ 让一切发生:Box=Box::new(123); 让taged_anything=从_框(1,anythin

给定一个包含
dyn Trait
对象的
Box
,有没有办法构造一个
Box
ed非大小化类型

例如,假设我有一个(可能)未调整大小的类型:

pub结构IdAndData{
id:i32,
数据:T,
}
是否有实现此签名的函数

pub-fn-construct\u from\u-box(id:i32,data:box)->box{
待办事项!()
}
这将允许如下操作:

fn main(){
让一切发生:Box=Box::new(123);
让taged_anything=从_框(1,anything)构造_;
}

我知道它必须消耗
数据
,为
id
数据
分配足够的空间,然后将
数据
移动到新的分配。这似乎是可能的(我们知道运行时的所有大小),但表明这只能通过使用切片进行非大小强制来完成


有没有安全的方法来执行此操作?

您链接的页面上显示:

目前,创建自定义DST的唯一受正确支持的方法是将类型设置为泛型并执行非大小强制:

(是的,定制DST目前基本上还不成熟。)

你所要求的东西在上下文中是完全合理的——它只是还不存在。取消大小调整强制要求在强制站点知道大小


我想,通过自由地应用
safe
,让它无论如何都能正常工作可能会很有趣什么都不要用它-我对编写好的<代码>不安全的<代码>生锈的代码不太熟悉,只是不断地修补一些东西,直到它起作用为止。甚至有可能用更少的危险来完成同样的事情

此代码仅用于娱乐目的。

#![功能(用于ptr的布局)]
#![功能(ptr_元数据)]
使用std::alloc;
使用std::alloc::Layout;
使用std::any::any;
使用std::mem::size\u of\u val;
使用std::ptr::addr_of_mut;
使用std::ptr::Pointee;
pub-fn从\u-box构造\u(id:i32,数据:box)->box{
//分解'data'指针。
让数据大小=值的大小(&*数据);
let(数据、元数据):(*const(),::元数据)=
(&*数据为*常数)至原始零件();
//错误地假设元数据肯定是相同的,并且
//重新解释,使类型匹配。
让强制的_元数据:::元数据=不安全{
*(&元数据为*const u为*const::metadata)
};
//弄清楚我们需要分配什么。
//安全性:布局::for_value_raw并不表示指针本身需要
//有效,只是它的元数据有效。
让结果_布局=不安全{
布局::针对原始值::(标准::ptr::来自原始零件(
&mut()作为*mut(),//无效,但未使用。
强制的元数据,
))
};
//为我们未来的盒子分配内存,
//并附加元数据。
让result_mem=unsafe{alloc::alloc(result_布局)};
如果结果_mem.为_null(){
alloc::handle\u alloc\u错误(结果\u布局);
}
让结果\u ptr:*mut id和data=std::ptr::from\u raw\u parts\u mut(
结果_mem为*mut(),
强制的元数据,
);
//将每个字段复制到新分配中。
不安全{
std::ptr::write(addr_of_mut!(*result_ptr.id),id);
std::ptr::复制\u不重叠(
数据ptr为*常数u8,
将_mut!(*result_ptr).data)的地址添加为*mut u8,
数据大小,
);
}
//释放旧的“数据”框,而无需对其内容运行drop
//只是复制。(有没有更好的方法来实现这一点,可能是使用ManuallyDrop?)
让data_layout=layout::for_值(&*data);
不安全{
alloc::dealloc(框::输入原始(数据)为*mut u8,数据布局);
};
//result_ptr现在已初始化,因此我们可以让Box管理它。
不安全{Box::from_raw(result_ptr)}
}

有趣的问题。我认为,虽然没有明显的理由不应该这样做,但DST表示是故意不指定的,因此以明显的方式工作可能会排除理想的未来扩展(自定义DST)。所以也许不是?我怀疑这可能就是答案。nomicon将定制DST称为半生不熟,我怀疑这仍然是最新的。我想没有需求(我只是把我需要的东西装箱就可以了),再加上DST表示的不确定性。那代码太糟糕了。。。已接受;)