在 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
不会用,不知道有没有别的办法? #![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()
此外,您可以阅读 there为什么fn get_id() -> Id<Box<dyn MyArticle>>
不起作用。
关于rust - 使用特征作为幻像类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67933762/