型消去 (: type erasure) とは、型変数が存在するクラスや構造体において、型変数を消去すること。

C++では、何らかの条件を満たす様々な型のオブジェクトをカプセル化し、テンプレートを使用しつつ実行時の多態性を実現する技法のことを言う。

以下のような利用例がある[1]

boost::anyおよびstd::any
代入・デストラクト可能なあらゆる型を保持できるクラス。
boost::functionおよびstd::function
クラステンプレートの型引数で関数のシグネチャ(仮引数・戻り値の型)を指定する。それと互換のあらゆる関数へのポインタや関数オブジェクトを保持できるクラステンプレート。
boost::shared_ptrおよびstd::shared_ptr
スマートポインタであり、削除子(デリーター、deleter)として、関数へのポインタや関数オブジェクトを指定できる。削除子の保有に型消去を利用している。

J2SE 5.0でジェネリックプログラミングを行うために、総称型が導入された。しかし、C++のテンプレートのように、異なる型引数のセットに応じて異なるクラスを作成することは、jarファイルの肥大化を招くと判断された。代わりに、どのような型引数が与えられても、型引数が消去 (型消去という用語はここから来ている) されたかのように見える[注 1]単一のクラスを用いることにした。以下のようなコードはコンパイルすることができない[注 2]

new T();
new T[]{};

また、以下のようなコードは意味がない[注 3]

T.someStaticMethod();
T.someStaticField;

型変数の出現箇所においては、型消去を行うフェーズで、適宜キャストがコンパイラによって暗黙的に挿入される。

java.lang.Object.getClass は Class<?>を返すと宣言されているが、任意のT型のインスタンスに対して呼び出すとClass<T'>を返す。ただし、T'Tのraw型である。

メリット

編集
  • 単一のクラス、構造体で済むために最適化などを行うコストが低い。

デメリット

編集
  • 型引数が異なる型でも区別できないため、型引数が異なる型同士でオーバーロードできない。

注釈

編集
  1. ^ 実際は外部から参照されるときのためにclassファイルのsignatureに型引数、及び型変数の情報が保存されている
  2. ^ Tが型変数の上限の型に置き換えられるためランタイム側で型を切り替えようとしても意味がない
  3. ^ Tが上限の型に読み替えられてコンパイルされる

出典

編集
  1. ^ 高橋晶、επιστημη「Chapter 7 Type Erasue 7‐3 Boostにおける使用例」『C++テンプレートテクニック』SBクリエイティブ、2009年、164頁。ISBN 978-4-7973-5453-9