今日は、TypeTraitsという概念についての自分の理解をまとめておきたい。
少なくとも、Traitsとは、型情報保持クラスとして使えるものである。具体的には、
template< class A, class B > class Traits { public: typedef A Atype; typedef B Btype; };
といったものが、例えばそうである。
これは何か。
これは、Traits クラスが具現化された時点で、その中のtypedef が実行されるというだけの仕掛けである。この一見とるに足らない仕掛けがどう便利なのか?
例えば、A, B, C という3つの型をその型引数としてわざわざ受け取らなくてはならないテンプレートクラス、もしくはそのようなテンプレートクラスのファミリーがあった場合、それらのクラスは皆、上記のTraitsクラス型を一つだけ、その型引数にとるように書き直せる。A, B, C の実際の型については、Traitsクラスが保持しており、これら型の利用者であるテンプレートクラス内部では、これらの型をそれぞれ、Atype, Btype, Ctype として参照できるのである。(後述するように、typenameキーワードを使う必要があるが、それだけだ。)
テンプレートの利用者はA, B, C という型情報を、Traitsの定義という形で一回だけ行えばよく、またテンプレートの記述者もテンプレート引数を最小限に抑えた、すっきりした記述ができるというわけなのである。
ただし、Traitsの利用側テンプレートでは、TypeTraits を、テンプレートパラメータTTとして受け取ったなら、
template< class TT > class User { public: private: typename TT::Atype m_a; }
などのように、"TT::Atype"を型名として参照させるために、typename キーワードが必要となる。最後に以下は、互いに循環参照する複数機能クラスの、共有Traitsを用いたテンプレートファミリー実装の、具現化例である。
class iFace; class iEdge; class iVertex; class iHalfEdge; typedef Mesh_Traits< iFace, iEdge, iVertex, iHalfEdge > MT; class iFace: public Face< MT >{ /* iFace独自の機能 */ }; class iEdge: public Edge< MT >{ /* iEdge独自の機能 */ }; class iVertex: public Vertex< MT >{ /* iVertex独自の機能 */ }; class iMesh: public Mesh< MT >{ /* iMesh独自の機能 */ };
おっとちなみにこれはCRTPでもありますね。はい。
最後に→こちら←は、ublas の CSparse のソース。冒頭部分は、クラス内型宣言で満たされたtype traits の宣言の嵐だね。
Modern C++ Design: Generic Programming and Design Patterns Applied (C++ In-Depth Series)
- 作者: Andrei Alexandrescu
- 出版社/メーカー: Addison-Wesley Professional
- 発売日: 2001/02/13
- メディア: ペーパーバック
- この商品を含むブログ (9件) を見る