rust - 使用特征作为幻像类型
问题描述
在 Rust 中,我想使用幻像类型来正确键入一个简单的 id:
struct Id<T> {
val: u32,
_type: PhantomData<T>,
}
在第一个草稿版本中,我使用了具体的结构T
,一切都很好。然后在使用不同数据源的更精细的版本中,这些结构变成了特征。比方说:
trait MyArticle {
fn get_id() -> Id<MyArticle>;
}
但是使用traits作为幻像类型会带来问题:
- 编译器让我声明
T: ?Sized
,好像T
是可能需要的大小。我可以忍受,但由于目的PhantomData<T>
是告诉它T
不会被使用,我想知道是否还有其他方法? - 我收到警告:“不推荐使用没有明确 'dyn' 的特征对象”。我可以用 global 摆脱它
#![allow(bare_trait_objects)]
,但是这个警告在其他方面很有用,我不想这样做。有没有办法bare_trait_object
只允许“当用作”的类型参数时Id<T>
?
我当前的解决方案是在空结构和特征之间复制名称类型:
struct MyArticle_ {};
trait MyArticle {
fn get_id() -> Id<MyArticle_>;
}
这很尴尬,但我找不到更好的。
解决方案
您的样本的问题在于了解特征是什么。实际上它不是类型(这就是编译器要求的原因T: ?Sized
),而是对类型的要求。因此解决方案相当简单:想出一个“真正的”类型。你用结构声明做对了,它可以是一种选择。但通常使用关联类型更方便:
trait MyArticle {
type T;
fn get_id() -> Id<Self::T>
where
Self::T: MyArticle;
}
// so given impls
struct X;
impl MyArticle for X {
type T = u32;
fn get_id() -> Id<u32> {
todo!()
}
}
impl MyArticle for u32 {
type T = u32;
fn get_id() -> Id<u32> {
todo!()
}
}
所以最后,你可以调用X::get_id()
,或者一个完全合格的版本:<X as MyArticle>::get_id()
此外,您可能会在那里阅读为什么fn get_id() -> Id<Box<dyn MyArticle>>
不起作用。
推荐阅读
- node.js - 无法在 Express App 中获取客户 IP 地址
- html - 如何让我的图像在 CSS 中通过?
- php - 如何为某个字段具有某个值的所有产品提取 xml 数据?
- admob - 可以使用实时 Admob 代码在测试设备上运行 Admob 广告吗?
- unity3d - 当我打开口型同步选项卡时,Unity 检查器 GUI 坏了
- c++ - 如何使用 Boost MSM 检索包含状态机
- javascript - 编译失败:找不到模块
- logging - Athena 经典负载均衡器日志
- sql - Oracle - to_date() 解析为 00:00:00
- php - response()->json 无法在 Laravel 中解码