rust - 允许使用用户定义的类型创建特征对象?
问题描述
在 Rust 中,引用以及Box<T>
、Rc<T>
和Arc<T>
允许创建特征对象(例如, fromBox<Type>
到Box<dyn Trait>
)。但是有没有办法允许使用用户定义的通用“智能指针”类型进行相同的转换?
例如,MyBox<T>
是一个瘦包装,Box<T>
但下面的代码会导致编译错误:
use std::io::Write;
pub fn main() {
let std_box: Box<Vec<u8>> = Box::new(Vec::new());
let std_dyn: Box<dyn Write> = std_box;
// ^ this conversion is allowed.
let my_box: MyBox<Vec<u8>> = MyBox { t: Box::new(Vec::new()) };
let my_dyn: MyBox<dyn Write> = my_box;
// ^ this conversion is not allowed.
}
struct MyBox<T: ?Sized> {
t: Box<T>,
}
error[E0308]: mismatched types
--> traits/src/trait_objs.rs:7:36
|
7 | let my_dyn: MyBox<dyn Write> = my_box;
| ---------------- ^^^^^^ expected trait object `dyn std::io::Write`, found struct `Vec`
| |
| expected due to this
|
= note: expected struct `MyBox<dyn std::io::Write>`
found struct `MyBox<Vec<u8>>`
解决方案
不幸的是,Rust Stable 的答案似乎是“你不知道”。Rust 非常保守,它允许隐式强制。特别是,从docs中,我们看到了适用于Box
.
允许在以下类型之间进行强制转换:
...
TyCtor(
T
) 到 TyCtor(U
),其中 TyCtor(T
) 是其中之一
&T
&mut T
*const T
*mut T
Box<T>
并且
U
可以T
通过unsized coercion从哪里获得。
其中相关的无大小强制规则是
T
todyn U
, whenT
实现U + Sized
, 并且U
是对象安全的。
那里没有太多空间可以放置特殊的外壳,至少在当前版本的 Rust 中没有。
但是,如果您愿意深入了解 Nightly 独有的功能,那么您将获得令人兴奋的CoerceUnsized
trait,其预期的用例是......指向会强制执行的事物的智能指针Box
。
#![feature(unsize, coerce_unsized)]
use std::ops::CoerceUnsized;
use std::marker::Unsize;
impl<T, U> CoerceUnsized<MyBox<U>> for MyBox<T> where T: Unsize<U>, U: ?Sized {}
这告诉 Rust 我们可以强制if is "basically the same" as ,MyBox<T>
以获得“基本相同”的适当定义。实现不需要函数;特质只需要存在。MyBox<U>
T
U
impl
推荐阅读
- airflow - 如何在 Airflow MySQL Operator 中使用 jinja 模板
- r - 使用可反应功能完成的表格未在 R Shiny 应用程序中显示
- python - 如何计算 CSV 文件中数字列表的中位数?
- javascript - .sort 不是数组上的函数
- javascript - 如何解决这个未捕获的引用错误:like_post 未在 HTMLAnchorElement.onclick 中定义?
- html - 如何分隔带图像的部分(浮动:左;)和不带图像的部分?
- java - 在 Springboot 中进行请求验证时,响应不符合预期
- javascript - IE 不支持箭头(=>)
- javascript - 角度日期和时间验证 MM/DD/YYY HH24MI
- javascript - 表单验证有效,但当用户输入错误答案时仍然提交