1

この質問を解決するために使用したCRTP ベースのテンプレート コードを次に示します。ここにコードを投稿しますが、行は長く、codepad.org の方が読みやすいです (必要に応じてここに投稿します)。もちろん、それは機能しますが、醜く、やや人工的です。しかし、MSVC++ と GCC の両方でコンパイルされますが、一部のテンプレート タイプは実際には定義されていないことに最初は気づきませんでした。私が質問している部分は、関数の上部にあるいくつかの長い内部if( typeid( Derived(N) ) != typeid( Derived(N-1))(記号表記)です。TBase::OnEvent

これらの型を使用することはできません。コンパイル エラーが発生します。typdefこのような長いチェーンで型を定義するための派生クラスが十分にない...::TDerived::...ため、正しくコンパイル エラーが発生しますTDerived is not defined in TBase。それでも、コンパイラはそれらを食べ尽くしますtypeid...::TDerived::...デバッガーの MSVC++ コンパイラー出力 (完全なシンボリック情報付き) をチェックインすると、実際にはどのクラスにもならないすべての longがtypeid、コンパイラーによって単にTDerived04クラス チェーンの最後に解決されたようです。そして、RTTI は、...::TDerived::...私が持っている数に関係なく、クラス チェーンの最後のクラスに対してプルされます。

MSVC++ と GCC の両方がそれを行うことを考慮して (私は codepad.org から GCC にしかアクセスできませんが)、私の質問は次のとおりtypeidです。では、なぜtypedefこれらの long のいずれかが に...::TDerived::...解決されないのTDerived04でしょうか?

編集:つまり、 が に解決typedefされないことをうれしく思います。TDerived04typedeftypeidtypedef

編集: GCC はTDerived04::TDerived04::TDerived04::TDerived04 lD4;変数宣言を受け入れます。そして、タイプは単にTDerived04最後にあります。スコープの解決を折りたたむためのルールはありますか? どうやら、MSVC++ と GCC の両方が で同じことを行っているようですが、typeidGCC とは異なり、MSVC++ は他のシナリオを処理できません。コンパイル エラーが発生し、コンストラクターの引数が必要になります。

4

2 に答える 2

1

大まかに問題は、注入されたクラス名とコンストラクター名の間にあいまいさがあることです。のスコープではclass XXクラス自体に名前を付けることがX::Xできますが、コンストラクターを参照することもできます

于 2012-01-03T11:53:33.243 に答える
1

typeidデバッグ用のツール以外に使用することは考えていません。C++ 標準はその存在を保証するだけで、実際に何をすべきかについては述べていません。これにより、このユーティリティは、人間が読めるクラス名を出力する方法にすぎません (他の実用的な使用法を知っている場合は、私を修正してください)。

typeid上記以外の目的で使用するには、「コンパイラ定義」の動作が多すぎると思います。

ソリューションで提示されたアプローチには、大きな欠点もあります。見苦しくて保守が難しいだけでなく、基本クラスはすべての派生クラスについて知る必要があります。これはかなり大きな設計上の欠陥です。

代替ソリューションについては、こちらで確認できます(コードは元の質問にも投稿されています)。

有効でTDerived04::TDerived04::TDerived04::TDerived04あることは、TDerived04 クラスで、その名前 TDerived04 を使用してこのクラス/名前空間を参照できることによって説明できます。したがって、TDerived04::TDerived04 は、TDerived04 からクラス TDerived04 を指すようなものです (@MSalters によると、「クラス名インジェクション」と呼ばれます)。

于 2012-01-04T09:53:56.123 に答える