テンプレートクラス

テンプレートクラスをうまく活用するとプログラムは簡単でしかも高速になります。

STLのvectorなどはテンプレートクラスです。ここでは、これらの仕組みを理解してより適切に使えるようになりましょう。

テンプレートクラスは、関数テンプレートに対しての呼び方です。テンプレートクラスは単にテンプレートと呼ばれるときがあります。

テンプレートの基本

テンプレートクラスでは、メンバ変数をテンプレート引数にすることができます。

template<class T>
class Test
{
public:
    T obj;
};

この例では、テンプレートクラスTestを定義しています。

使い方は

Test<int> num;
num.obj = 1;

の様になります。

Test<int> num;

という記述が現れた時、上のテンプレートクラスからTがintに置き換わって

class Test
{
public:
    int obj;
};

が作られます。このようにテンプレートから具体的なクラスが出来ることをテンプレートのインスタンス生成と呼びます。

テンプレート引数にはintcharのような通常の型やクラスを指定できます。ポインタも指定できます。基本的にはテンプレート引数を置き換えたときにつじつまがあっていれば良いということになります。

テンプレート引数は複数指定することが出来ます。

template<class X, class Y>
class Test2
{
public:
    X obj1;
    Y obj2;
};

使うときは、例えば、

Test2<char*, int> foo;

の様にします。この場合Xがchar*に、Yがintにそれぞれ置き換わります。

テンプレートクラスも派生したり、されたりすることが出来ます。以下に例を示します。

class Test3 : public Test2<int, double>
{
};

class DummyClass //通常のクラス
{
public:
    char c;
};

template<class A>
class Test4 : public DummyClass //通常のクラスから派生
{
public:
    A m;
};

template<class B, class C>
class Test5 : public Test2<B, C> //テンプレートから派生した新しいテンプレート
{
};

テンプレートクラスを定義する

それでは、以前説明で使った、クラスObjectとその派生クラスInt, Char, Textをテンプレートを使って実現してみましょう。

Int, Char, Textをよく見ると良く似た形をしています。それぞれのメンバ変数i,c,tはテンプレート引数に出来そうです。ここでは名前を統一してobjにしましょう。テンプレートクラスは以下の様になります。

template <class T>
class TempObj : public Object
{
    T obj;
    void print(); //ここはどうするの?
};

TempObjが新しいテンプレートクラスの名前です。Objectから派生しています。いままで具体的な型だった部分がテンプレート引数であるTになっています。メンバ変数はobjです。しかし、メンバ関数printは型によって記述が違いますのでどのように書いたらいいでしょうか?

これは、関数テンプレートと同じように特別バージョンを記述します。このようになります。

void TempObj<int>::print()
{
    printf("%d\n", obj);
}

void TempObj<char>::print()
{
    printf("%c\n", obj);
}

void TempObj<char*>::print()
{
    printf("%s\n");
}

このように<>の中にTが具体化されたときの型を記述します。この例ではTにintとcharとchar*を与えた場合だけコンパイルは成功します。 それ以外の物が与えられるとエラーになります。 それ以外の物が与えられたときのために以下のように記述することも出来ます。上の3つに加えて、

template<class T>
void TemObj<T>::print()
{
    printf("表示の仕方が分かりません。\n");
}

このように記述します。他の型が与えられた場合はこの関数が実行される様になります。

それではプログラムの全体像です。

プロジェクト名: tc1

main関数の中で、テンプレートクラスTempObjがどのように使われているか注意してください。

このプログラムでは、double型のデータを表示できません。

実行結果は以下のようになります。

問題

プロジェクト名:tc2

tc1をもとにして、double型が正しく表示されるように修正してください。

 

さて、これで、STLのvectorがどのような仕組みになっているかなんとなく分かってきたのではないでしょうか。

 

ストリームへ進みます。