如何将具体类型的自定义结构体克隆为 trait 对象?
Rust中Wrapper<Rc>无法从具体类型克隆转换为trait对象的问题解析
问题背景
在Rust中:
Rc<usize>可以直接克隆并转换为Rc<dyn Foo>(当usize实现Footrait时);- 定义
Wrapper<T: ?Sized>(Rc<T>)结构体后,能直接创建Wrapper<dyn Foo>实例; - 但尝试将
Wrapper<usize>克隆为Wrapper<dyn Foo>时,编译器会报类型不匹配错误。
问题原因
- Rc的特殊处理:
Rc<T>实现了impl<T: ?Sized> Clone for Rc<T>,当T实现某个trait时,Rc<T>可以被强制转换为Rc<dyn Trait>。在let y: Rc<dyn Foo> = x.clone();中,实际是先克隆得到Rc<usize>,再自动完成强制转换为Rc<dyn Foo>。 - Wrapper的自动Clone限制:
Wrapper<T>通过#[derive(Clone)]自动生成的Clone实现,签名为fn clone(&self) -> Wrapper<T>,返回类型与原实例完全一致(即Wrapper<usize>)。Rust不会自动将Wrapper<usize>(Sized类型)强制转换为Wrapper<dyn Foo>(unsized trait对象),因为自定义结构体默认不支持这种跨类型的DST转换,必须手动实现转换逻辑。
解决办法
方法1:显式转换内部Rc后重新包装
直接取出Wrapper内部的Rc<T>,克隆并转换为Rc<dyn Foo>,再重新包装成Wrapper:
use std::rc::Rc; trait Foo {} #[derive(Clone)] struct Wrapper<T: ?Sized>(Rc<T>); impl Foo for usize {} fn main() { let x: Wrapper<usize> = Wrapper(Rc::new(1)); let y: Wrapper<dyn Foo> = Wrapper(x.0.clone()); }
方法2:给Wrapper添加自定义转换方法
为实现了Foo的具体类型Wrapper<T>添加一个方法,专门克隆并转换为trait对象版本的Wrapper:
use std::rc::Rc; trait Foo {} #[derive(Clone)] struct Wrapper<T: ?Sized>(Rc<T>); // 为实现Foo的Sized类型的Wrapper添加转换方法 impl<T: Foo + Sized> Wrapper<T> { fn clone_dyn(&self) -> Wrapper<dyn Foo> { Wrapper(self.0.clone()) } } impl Foo for usize {} fn main() { let x: Wrapper<usize> = Wrapper(Rc::new(1)); let y: Wrapper<dyn Foo> = x.clone_dyn(); }
方法3:实现From trait支持类型转换
通过实现From<Wrapper<T>> for Wrapper<dyn Foo>来支持显式转换:
use std::rc::Rc; trait Foo {} #[derive(Clone)] struct Wrapper<T: ?Sized>(Rc<T>); impl<T: Foo + Sized> From<Wrapper<T>> for Wrapper<dyn Foo> { fn from(value: Wrapper<T>) -> Self { Wrapper(value.0) } } impl Foo for usize {} fn main() { let x: Wrapper<usize> = Wrapper(Rc::new(1)); let y: Wrapper<dyn Foo> = x.clone().into(); }
内容的提问来源于stack exchange,提问作者Román Cárdenas
相关产品推荐
相关产品推荐

