普通に考えると無理なのですが、例えば boost::shared_ptr<void> とかのスマートポインタを使えば出来るんじゃないかなと思ってみたりしています。
boost::shared_ptr<void> の正しい型を IHoge を継承した Hoge クラスだとして、変換先の型を IHoge だとすれば、
boost::shared_ptr<void> p(new Hoge);
boost::shared_ptr<IHoge> hoge = real_dynamic_cast<IHoge>(p);
boost::shared_ptr<HogeEx> hoge2 = real_dynamic_cast<HogeEx>(p);
となるのが目標です。
パッと見無理そうなのですが、boost::shared_ptr<> 等の優れたスマートポインタは元の型の情報を保持しているので、何とかならないかなぁと考えてみました。
壁は2つあります。
1.元の型の情報というのは静的に解決出来るものではなく、つまり静的に型が決まらないので dynamic_cast<> が使えない。
2.仮想テーブルを持っていないクラスは継承関係が判断できないので、そのクラスをどうするか。
1は結構致命的です。継承関係を判断しながらキャストするのは dynamic_cast<> じゃないと不可能(type_info は同じか否かしか判断できない)ので、かなり難しそうです。
で、さらに調べていると面白い関数を見つけました。
VS2005 では dynamic_cast<> というのは内部で __RTDynamicCast という関数を呼び出しているみたいで、それを Google Code Search で検索してみると、そのソースがありました。
rtti.cpp
処理を見てみると、type_info を引数に取っているっぽいです。
ということは、別に静的に dynamic_cast<> する必要なんかなくて、boost::shared_ptr<> で正しい型の type_info をどっかに保持しておいて、それを使ってキャストすればいいんですね。
これで1の問題は解決しそうだなぁと思って(↑の rtti.cpp の __RTDynamicCast ではなくて)VS2005 の __RTDynamicCast を使ってみたのですが、
にあるように、今までの __RTDynamicCast に比べて制限が厳しくなってるっぽいです。
となると rtti.cpp の __RTDynamicCast を使うしか無いかなと思ったんですけど、そもそもこんな超ランタイム依存コードを書いてしまってもいいのかという疑問もわき上がってきました。
さてどうしよう、というところで思考が止まってます。
void* を型安全でキャストするなんてことはやめとけってことなんでしょうかね……。