Rust中的幽灵类型(PhantomData)
现在有两个数据结构分别为User和Product,它们都有一个u64类型的id,有一个需求是每个数据结构的id只能和同种类型的id比较,如果user.id和product.id比较,编译器就能直接报错,该如何实现?
首先,可以设计一个inner数据结构来表示id,利用泛型将外层数据结构Self传入,已达到两个不同类型的inner不能比较的效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #[derive(Debug, Default, PartialEq, Eq)] struct Identifier<T> { inner: u64, }
#[derive(Debug, Default, PartialEq, Eq)] struct User { id: Identifier<Self>, }
#[derive(Debug, Default, PartialEq, Eq)] struct Product { id: Identifier<Self>, }
fn main() { let user = User::default(); let product = Product::default();
assert_ne!(user.id, product.id); }
|
但此时上述代码无法通过编译,报错信息为
parameter T
is never used
泛型T未被使用,编译器认为T是多余的
此时我们可以通过PhantomData来解决,PhantomData顾名思义就是幽灵类型,它被广泛用在处理,数据结构定义过程中不需要,但是在实现过程中需要的泛型参数。PhantomData实际上长度为零,是个ZST(Zero-Sized Type),就像不存在一样,唯一作用就是类型的标记。
最终效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| use std::marker::PhantomData;
#[derive(Debug, Default, PartialEq, Eq)] struct Identifier<T> { inner: u64, _tag: PhantomData<T>, }
#[derive(Debug, Default, PartialEq, Eq)] struct User { id: Identifier<Self>, }
#[derive(Debug, Default, PartialEq, Eq)] struct Product { id: Identifier<Self>, }
fn main() { let user = User::default(); let product = Product::default();
assert_ne!(user.id, product.id); }
|
参考
[1]陈天·Rust编程第一课