// dictionary
ユニット様構造体.
ユニット様構造体(unit-like struct)は、フィールドを1つも持たない構造体です。struct Marker;のようにフィールドリストごと省略して定義します。保持する値がない点がユニット型()に似ているため、この名前で呼ばれます。
定義すると型と同じ名前の定数が暗黙に作られるため1、Markerと書くだけでインスタンスが得られます。
struct TaxCalculator; // 税率10%固定。覚えておくべきデータがない
impl TaxCalculator {
fn total(&self, price: u32) -> u32 {
price * 110 / 100
}
}
fn main() {
let calculator = TaxCalculator; // 型名をそのまま書くとインスタンスになる
println!("税込み: {}円", calculator.total(1000));
}Playgroundで開く使いどころ
フィールドがなくてもimplブロックは書けるので、メソッドや関連関数を持たせられます。上の例のように状態は持たずに処理だけをまとめたい型や、データは持たせずトレイトの実装だけを与えたいマーカー型が主な用途です。
フィールドを持たない3つの書き方
フィールドが0個の構造体は次の3通りに書けます。型としてはどれもフィールドを持ちませんが、同じ名前で値の名前空間に何が定義されるかが異なります。
| 定義 | 種類 | Marker単体の意味 |
|---|---|---|
struct Marker; |
ユニット様構造体 | インスタンス(暗黙の定数) |
struct Marker {} |
フィールド0個の構造体 | 値ではない(E0423エラー) |
struct Marker(); |
フィールド0個のタプル構造体 | コンストラクタ関数 |
struct Marker {}のような波括弧での生成はどの形でも書けるため、違いが出るのはMarkerと単体で書いたときです。struct Marker;はstruct Marker {}とconst Marker: Marker = Marker {};を同時に書いたのと等価で1、単体でインスタンスになるのはこの形だけです。
補足
サイズは0バイト・Debug出力は型名
ユニット様構造体はフィールドを持たないため、実行時のメモリを占有しません。名前付きフィールドの構造体と同じく#[derive(Debug)]も使え、{:?}では型名がそのまま出力されます(コンソール出力も参照)。
#[derive(Debug)]
struct Marker;
fn main() {
println!("{}バイト", size_of::<Marker>()); // 0バイト
println!("{:?}", Marker); // Marker
}Playgroundで開く標準ライブラリでの例
std::marker::PhantomDataは標準ライブラリのマーカー型で、ジェネリクスを伴うユニット様構造体としてpub struct PhantomData<T> where T: ?Sized;と宣言されています2。実際に値を持たないまま「この型を使っているつもり」という情報だけをコンパイラに伝える、マーカー型の代表例です。
Footnotes
-
The Rust Reference: Structs — フィールドリストを完全に省略した構造体をunit-like structと呼び、同名の定数を暗黙に定義すると述べています。 ↩ ↩2
-
std::marker::PhantomData — 宣言そのものが記載されています。 ↩
この辞書が使われているページ
backlinks 3