2006-08-27
今月はバタバタしていてなかなか更新ができませんでした。決して更新が面倒になって放置しているわけではありませんので、今後ともよろしくお願いします。
今回はクラステンプレートについてお話します。クラステンプレート自体は関数テンプレートの延長のようなものですが、話を簡単にするために、今回は単純な構造体を使って話を進めることにします。
C言語には、整数の商と剰余を格納するための div_t 型という構造体があります。これは div 関数の返却値型となるものです。div_t 型は商と剰余を int 型で格納するものですが、long 型版として ldiv_t 型が、long long 型版として lldiv_t 型というのがあり、それぞれ ldiv 関数と lldiv 関数の返却値型となります。
C++にも div_t 型や ldiv_t 型、および div 関数や ldiv 関数はありますが
*1、関数に関しては、ldiv 関数と同じものが div 関数として多重定義されています。しかし、ldiv_t 型はそのままなので、どうしても使用する型に応じて字面を変えなければなりません。そこで、div_t 型と ldiv_t 型をテンプレートにしてみましょう。
template <typename T>
struct xdiv_t
{
T quot;
T rem;
};
既存のものと名前が衝突しないように xdiv_t としましたが、接頭辞の x に深い意味はありません。このように、クラス(ここでは構造体ですが、構造体もクラスの一種です)全体をテンプレートにしたものを「クラステンプレート」といいます。
クラステンプレートを使用するには、テンプレート引数(ここでは T )に適切な型を与えて具現化しなければなりません。それには
xdiv_t<int> といった記法を用います。xdiv_t<int> であれば、テンプレート引数に int 型を指定したわけです。
次に、この xdiv_t クラステンプレートを返す xdiv 関数テンプレートも作ってみましょう。
template <typename T>
xdiv_t<T> xdiv(T numer, T denom)
{
xdiv_t<T> result;
result.quot = numer / denom;
result.rem = numer % denom;
return result;
}
ここで、除算や剰余算の一方の演算対象が負の場合の結果が処理系定義なる話は、今回の内容とは直接関係ないので触れないことにします。このような xdiv_t クラステンプレートおよび xdiv 関数テンプレートを定義することで、実際に使用する型をパラメータ化することができ、具体的な型に依存しないコードを書くことができるようになります。
ジェネリックプログラミングないしはテンプレート・メタプログラミングにおいては、具体的な型をハードコーディングするのは、具体的な値を即値としてハードコーディングする(いわゆるマジックナンバー)のに等しい行為です。
状況によっては、その型でなければならない場合や、何でもよいので int 型にする場合もありますが、それは値でも同じことがいえますね。
*1 C++には long long 型がないので、lldiv_t 型や lldiv 関数はありません。
Comment