Rust自定义智能指针能否支持trait对象的创建与转换?
问题核心原因
- Rust 中支持自定义泛型智能指针实现和
Box<T>一样的trait对象自动转换,前提是实现标准库的CoerceUnsizedtrait,这个trait是编译器用于处理unsized 强制转换的核心特性,标准库的Box<T>、Rc<T>、Arc<T>都内置了这个trait的实现,所以支持直接从Box<具体类型>转换为Box<dyn Trait>。 - 目前
CoerceUnsized属于不稳定特性,仅能在nightly版本的Rust中使用,稳定版暂未开放该特性的自定义实现权限。
Nightly 版本的实现示例
你需要先在代码顶部开启对应的特性门,然后为MyBox<T>实现CoerceUnsized即可支持自动转换:
// 开启不稳定特性 #![feature(coerce_unsized)] #![feature(unsize)] use std::io::Write; use std::ops::CoerceUnsized; use std::marker::Unsize; pub fn main() { let std_box: Box<Vec<u8>> = Box::new(Vec::new()); let std_dyn: Box<dyn Write> = std_box; // 转换合法 let my_box: MyBox<Vec<u8>> = MyBox { t: Box::new(Vec::new()) }; let my_dyn: MyBox<dyn Write> = my_box; // 现在转换可以正常通过编译 } struct MyBox<T: ?Sized> { t: Box<T>, } // 为MyBox实现CoerceUnsized,支持从T到U的unsized强制转换 impl<T, U> CoerceUnsized<MyBox<U>> for MyBox<T> where T: Unsize<U> + ?Sized, U: ?Sized, {}
稳定版替代方案
如果要在稳定版Rust中实现类似效果,无法使用自动强制转换,只能手动定义转换方法:
use std::io::Write; pub fn main() { let my_box: MyBox<Vec<u8>> = MyBox { t: Box::new(Vec::new()) }; // 调用手动实现的转换方法得到trait对象版本的MyBox let my_dyn: MyBox<dyn Write> = my_box.into_dyn(); } struct MyBox<T: ?Sized> { t: Box<T>, } impl<T> MyBox<T> { // 手动实现转换为dyn Write的方法,如果要适配任意trait可以进一步用泛型封装 pub fn into_dyn(self) -> MyBox<dyn Write> where T: Write + 'static, { MyBox { t: self.t } } }
内容的提问来源于stack exchange,提问作者mxxk
相关产品推荐
相关产品推荐

