「 Curiously Recurring Template Pattern 」の実用的な用途は何ですか? 一般的に示されている「カウントされたクラス」の例は、私にとって説得力のある例ではありません。
5 に答える
シミュレートされた動的バインディング。階層的な利点の一部を保持しながら仮想関数呼び出しのコストを回避することは、私が現在取り組んでいるプロジェクトで実行できるサブシステムにとって大きなメリットです。
また、ミックスイン(つまり、機能を提供するために継承するクラスを意味します)にも特に役立ちます。ミックスイン自体は、操作対象の型を知る必要があります (したがって、テンプレートである必要があります)。
効果的な C++ では、Scott Meyers が例としてクラス テンプレート NewHandlerSupport<T> を提供しています。これには、(std::set_new_handler がデフォルトのオペレーター new に対して行うのと同じ方法で) 特定のクラスの new ハンドラーをオーバーライドする静的メソッドと、ハンドラーを使用するオペレーター new が含まれます。型ごとのハンドラーを提供するために、親クラスは、それがどの型に作用しているかを知る必要があるため、クラス テンプレートである必要があります。テンプレート パラメータは子クラスです。
CRTP なしでは実際にはこれを行うことはできません。それを使用するクラスごとに、現在の new_handler を格納する別の静的データ メンバーを使用して、NewHandlerSupport テンプレートを個別にインスタンス化する必要があるためです。
明らかに、例全体は非常にスレッドセーフではありませんが、要点を示しています。
Meyers は、CRTP は「Do It For Me」と考えられるかもしれないと示唆しています。これは一般的にどの mixin にも当てはまり、CRTP は mixin クラスだけでなく mixin テンプレートが必要な場合に適用されます。
スーパークラスに渡されるサブクラスの型がメソッドの展開時にのみ必要であると考えると、CRTP はあまり興味をそそられなくなります。したがって、すべてのタイプが定義されます。シンボリック サブクラスの型をスーパークラスにインポートするためのパターンが必要なだけですが、スーパークラスに関する限り、すべての正式なテンプレート パラメーター型は定義により定義されているため、それは単なる前方宣言です。
スーパークラスが派生型のオブジェクトを返すことを可能にするために、特性型構造のサブクラスをスーパークラスに渡すことで、多少変更された形式で使用します。アプリケーションは、すべての一般的な機能がスーパークラスに実装されている幾何学的計算 (点、ベクトル、線、ボックス) のライブラリであり、サブクラスは特定の型を定義するだけです: CFltPoint は TGenPoint から継承されます。また、CFltPoint は TGenPoint の前に存在していたため、サブクラス化はこれをリファクタリングする自然な方法でした。
一般に、実行時に派生クラスを選択できる必要がなく、コンパイル時にのみ選択できるポリモーフィックのようなパターンに使用されます。これにより、実行時の仮想関数呼び出しのオーバーヘッドを節約できます。
実際のライブラリでの CRTP の使用については、ATL と WTL (wtl.sf.net) を参照してください。コンパイル時のポリモーフィズムのために広く使用されています。