******************************************************************** * * * STLportコンテナでのポインタ特殊化に関するドキュメント. * * * ******************************************************************** なんのために行うか: テンプレートコードの大きな問題点はコンパイルされたバイナリサイズ が潜在的に巨大になりやすいことだ。 生成されるバイナリが同一になるにしても、各々テンプレート型を実体 化するとコンパイラは新しい別の型として生成する。 このバイナリのダブリを回避するため STLport では以下の4つのコンテナ について部分的なポインタの特殊化を行う。 - vector - deque - list - slist どのような動作か: このポインタ特殊化は、CV修飾型含むポインタを要素にもつ任意のコン テナに対し、void* コンテナのインスタンス化を利用するというものだ。 根本的には単に、全てのメソッド呼出を void*コンテナ・インスタンスへ ブリッジするだけ。ブリッジとしてすることは、void* 型から目的のポイ ンタ型へのキャストだけ。 なぜ4コンテナのみか: なぜ連想コンテナやハッシュコンテナで特殊化しないのかと不思議に思 う人もいるかもしれない。 例として set コンテナを見てみる。その宣言は、 template , class _Alloc = allocator<_Tp> > class set; 最初に、以下のような部分特殊化について考えてみる。 template class set<_Tp*, _Compare, _Alloc> このような部分特殊化の場合、基礎となるコンテナはどうなるだろう? _Alloc 型は _VoidAlloc 型を 簡単に見いだせるように rebind メンバー メソッドを持っている。一方 _Compare型は通常この種の要件を持たない。 なので _compare 型をラップした、全てのキャストを行うための _WrapCompare 型が必要になる。 基礎となるコンテナ型は次のようになるだろう。 set, _VoidAlloc> 問題は、_WrapCompare のインスタンス化は元の _Tp 型に依存していると いうことだ。これだと set のインスタンス化ではそれぞれ異なる void* コンテナとなるので、バイナリがダブる事態が発生してしまう。 次に、以下のような部分特殊化を制限する場合を考えてみる。 template class set<_Tp*, less<_Tp*>, _Alloc> 比較ファンクタが 標準 less 構造体の場合のみ set コンテナを特殊化す るとする。基礎となるコンテナを次のようにする。 set, _VoidAlloc> これは一見まともに見えるが不味い。lessのような基本的なモノであって も実際にはSTL ユーザーが自由に特殊化できる。このような場合、クライ アントは 独自ファンクタによって set が順序付けされると思っているの に 実は less ファンクタで順序付けられていた、という不具合に なる。less 特殊化問題もまた基礎となるのは set, _VoidAlloc> はありえず set, _VoidAlloc> だろうことを示している。ここで __less は標準 less ファンクタと等価 であるが、クライアント・コードから呼ばれないので特殊化されることが ない。 もちろんこの特殊化の問題は解決できる。less特殊化を検出できる必要 があり、厳格な演算子順序に基づいた STLport実装のデフォルトの less ファンクタのみならば setの部分特殊化は行えるだろう。この問題の解決 策がすぐにみつかることには疑いはない。