2006-07-23
豊富なC++の機能のうち、型識別はあまり使われていないような気がします。実際のところ、あまり使い勝手がよいとはいえませんが、特定の状況、例えばオブジェクト・ファクトリやマルチ・メソッドといったことをやりたいときには、それなりに役に立ちます。オブジェクト・ファクトリやマルチ・メソッドについてはここでは詳しく書きません。検索エンジンなどで調べてみてください。
型識別を使うための文法は簡単で、
typeid というキーワードを sizeof のように使います。すなわち、typeid(式) または typeid(型) とします。sizeof と違って、オペランドが式の場合も括弧が必須です。typeid は<typeinfo>ヘッダで宣言される
std::type_info クラスへのconst参照を返します。
通常はオペランドは評価されませんが、式が多相クラス
*1へのポインタや参照の場合は評価されます。その場合、式がオブジェクトを指していなければ(空ポインタなど)std::bad_typeid 例外が送出されます。
同じ型に対するtypeidが返すstd::type_infoクラス(またはその派生クラス)への参照は常に同じオブジェクトを指しているとは限りません。具体的には、同じ型であっても翻訳単位ごとに別の実体を指している可能性があるわけです。したがって、std::type_infoへのポインタを比較することで型の同一性を確認することはできません。std::type_infoでは等価演算子が多重定義されていますので、それを使用する必要があります。
std::type_infoクラスには before メンバ関数というのがあります。これは処理系定義の方法でstd::type_infoが表現する型の順序付けを行うためのものですが、関係演算子ではないのでやや使い勝手がよくないようです。
また、std::type_infoクラスには name メンバ関数というのがあります。これは型名を表す文字列ですが、完全に処理系定義である上に、型に対してユニークであるかどうかも分からないので、少なくとも移植性を考慮するとほとんど使い物になりません。実際、Visual C++などでは可読性の高い文字列が得られますが、GCCではかなり暗号的です。
ここまでざっと typeid および std::type_info について駆け足で見てきましたが、まともに使えるようにするには、
「Modern C++ Design」でも紹介されているように、何らかのラッパ・クラスを作った方がよさそうです。
*1 仮想関数を持つクラスのこと。
Comment