サイズがゼロの型は ZST (Zero Sized Types) と呼ばれる。

対象の型

以下の型は ZST として扱われる。

利用方法

とりあえず ZST を利用したい場合、空のタプル () が使われる事が多い。

より具体的な方法については『空のタプル (ユニット)』を参照。

補足: アドレスの確保

おそらく滅多に使われない機能だと思われるが、気付いたので一応メモしておく。

ZST の読書時のサイズはゼロだが、アドレスは用意される場合がある。

変数の場合

ZST を通常の変数として用意した場合、アドレスを識別するための最低限度のメモリ領域が確保される。


fn main() {
    let zst1 = Zst;
    let zst2 = Zst;
    dbg!(&zst1 as *const _);
    dbg!(&zst2 as *const _);
}

pub struct Zst;

[src\main.rs:4] &zst1 as *const _ = 0x000000c08ecfeb70
[src\main.rs:5] &zst2 as *const _ = 0x000000c08ecfeb78

なお、配列では要素ごとのアドレスが重複する。


fn main() {
    let arr = [Zst, Zst];
    dbg!(&arr[0] as *const _);
    dbg!(&arr[1] as *const _);
}

pub struct Zst;

[src\main.rs:3] &arr[0] as *const _ = 0x00000089702fec08
[src\main.rs:4] &arr[1] as *const _ = 0x00000089702fec08

Box の場合

Box と ZST の組合せは何の役にも立たない。

アドレスを識別するためのメモリすら用意されない。


fn main() {
    let zst1 = Box::new(Zst);
    let zst2 = Box::new(Zst);
    dbg!(Box::into_raw(zst1));
    dbg!(Box::into_raw(zst2));
}

pub struct Zst;

[src\main.rs:4] Box::into_raw(zst1) = 0x0000000000000001
[src\main.rs:5] Box::into_raw(zst2) = 0x0000000000000001

Vec の場合

Vec と ZST の組合せも何の役にも立たない。

各要素ごとにも全体でもメモリは用意されない。


fn main() {
    let vec1 = vec![Zst];
    let vec2 = vec![Zst];
    dbg!(&vec1.as_slice()[0] as *const _);
    dbg!(&vec2.as_slice()[0] as *const _);
}

pub struct Zst;

[src\main.rs:4] &vec1.as_slice()[0] as *const _ = 0x0000000000000001
[src\main.rs:5] &vec2.as_slice()[0] as *const _ = 0x0000000000000001