#type #associated #canonical #ext #enums #phantom-data #assoc

无 std the_assoc_ty_ext

规范关联类型(如 New Type 习语所示)

1 个不稳定版本

0.1.0 2022年2月11日

#383无标准库


用于 2 个 Crates(通过 zst

MIT/Apache

9KB

规范关联类型(如 New Type 习语所示)

将类型本身作为值的一种表示方式,而不是其值的本身,一种很好的方法是使用 零大小类型,通常简称为 ZST。程序员可以为枚举创建一个变体,该变体存储相应的 ZST(以及隐式地,可能被优化掉的 枚举区分符);然后枚举的大小将不会依赖于所表示的类型的大小。

在撰写本文时,尚无规范包装器可用来获取表示类型的 ZST。最接近的替代品是 core::marker::PhantomData,然而 PhantomData 的语义 过于丰富,并且在这方面的通用性/易用性之间存在着不希望的权衡,对于这种情况,是次要的使用场景

注意:更精确地说,所需的泛型 ZST<T> 新类型与 PhantomData<*const T> 非常接近。

由于 ZST<T> 必须表示 T,因此自然希望访问关联类型。此包提供 TheAssocTyExt 特性,该特性旨在为任何具有希望访问的关联类型的类型实现。

示例

use the_assoc_ty_ext::TheAssocTyExt;
use core::{
    default::Default,
    mem::{size_of, size_of_val},
    marker::PhantomData
};

#[derive(Default)]
struct ZST<T: ?Sized>(PhantomData<*const T>);

impl<T: ?Sized> TheAssocTyExt for ZST<T> {
    type TheAssocTy = T;
}

// Repr is necessary to ensure the size of the discriminant
#[repr(u8)]
enum PrimUnsignedIntKinds {
    U8(ZST<u8>),
    U16(ZST<u16>),
    U32(ZST<u32>),
    U64(ZST<u64>),
    U128(ZST<u128>),
    Usize(ZST<usize>),
}

assert_eq!(size_of::<ZST<u16>>(), 0);
assert_eq!(
    size_of_val(&PrimUnsignedIntKinds::U16(ZST::<u16>::default())),
    size_of::<u8>()
);
assert_eq!(
    size_of::<PrimUnsignedIntKinds>(),
    size_of::<core::mem::Discriminant<PrimUnsignedIntKinds>>()
);

注意core::mem::Discriminant,如文档所述,是一个不透明数据类型。类似地,出于性能考虑,任何enum的数据布局都相当模糊。你可以在不安全代码指南参考中了解更多详情。

无运行时依赖