幽霊型パラメータ

幽霊型とは実行時には存在しないけれども、コンパイル時に静的に型チェックされるような型のことです。

構造体などのデータ型は、ジェネリック型パラメータを一つ余分に持ち、それをマーカーとして使ったりコンパイル時の型検査に使ったりすることができます。このマーカーは実際の値を何も持たず、したがって実行時の挙動そのものにはいかなる影響ももたらしません。

以下の例では、そのようなマーカーとして幽霊型(std::marker::PhantomData)を用い、それぞれ異なった型の値を持つタプルを作成します。

use std::marker::PhantomData;

// ジェネリックなタプル構造体。2つ目のパラメータは幽霊型。
#[derive(PartialEq)] // 比較演算子(`==`)での比較を可能にします。
struct PhantomTuple<A, B>(A, PhantomData<B>);

// 同様に構造体を定義。
#[derive(PartialEq)] // 比較演算子(`==`)での比較を可能にします。
struct PhantomStruct<A, B> { first: A, phantom: PhantomData<B> }

// 注意点:  ジェネリック型Aに対してはメモリが割り当てられていますが、
//          Bには割り当てられていないため、計算に使うことはできません。

fn main() {
    // ここで `f32` と `f64` は隠しパラメータです。
    // <char, f32>と型宣言されたPhantomTupleを作成。
    let _tuple1: PhantomTuple<char, f32> = PhantomTuple('Q', PhantomData);
    // <char, f64>と型宣言されたPhantomTupleを作成。
    let _tuple2: PhantomTuple<char, f64> = PhantomTuple('Q', PhantomData);

    // <char, f32>の型が与えられた構造体を作成。
    let _struct1: PhantomStruct<char, f32> = PhantomStruct {
        first: 'Q',
        phantom: PhantomData,
    };
    // 同様に<char, f64>の構造体
    let _struct2: PhantomStruct<char, f64> = PhantomStruct {
        first: 'Q',
        phantom: PhantomData,
    };

    // コンパイルエラー!型が違うので比較することができません!
    // println!("_tuple1 == _tuple2 yields: {}",
    //           _tuple1 == _tuple2);

    // コンパイルエラー! 型が違うので比較することができません!
    // println!("_struct1 == _struct2 yields: {}",
    //           _struct1 == _struct2);
}

参照

導出, 構造体, タプル構造体