C++テンプレート

C++のテンプレートとは

C++におけるテンプレートは、汎用的な関数またはクラスを作成できる仕組みです。

テンプレートを利用してデータ型を固定しない関数やクラスを作成することで、様々なデータ型で共用することができます。

テンプレートは再利用可能なプログラムの作成を可能とする機能といえます。


汎用関数(関数テンプレート)

汎用関数とは

汎用関数とは、テンプレートを利用した「引数と返り値の型が決まっていない」関数です。

テンプレートを用いると、1つの関数を様々なデータ型に適用できるため、型ごとに関数を作成する必要がなくなります。


汎用関数の作成

テンプレートを用いて汎用関数を作成するには、「template」キーワードを使い関数を定義します。


template <typename T> 戻り値 関数(){ ... }

ここでの「T」はtypeの意味であり、関数が受け取る汎用データ型です。「T」は実際に存在する型ではなく、コンパイル時には各データ型に対応した型の関数が生成されます。

また、typenameの代わりに「class」キーワードを用いることも可能です。


#include <iostream>

// 変数の値を入れ替える。
template <typename T>
void tmpl_swap(T &a, T &b)
{
    T temp;
    temp = a; a = b; b = temp;
}

int main()
{
    int  x = 10, y = 20;
    char c = 'p', d = 'q';

    tmpl_swap(x, y); printf("%d,%d\n", x, y);
    tmpl_swap(c, d); printf("%c,%c\n", c, d);

    return(0);
}

型の強制

テンプレート関数は、コンパイラが引数の型にあわせて自動で<typename T>のTを決定しますが、これを強制的に指定することもできます。

強制する場合には以下の形式で関数を呼び出します。


関数<型>(引数 ...)

型を強制することで、テンプレートの使い方が非常に多岐に渡ります。


#include <iostream>

// 変数の値を入れ替える。
template <typename T>
T add(T a, T b)
{
    return(a + b);
}

int main()
{
    int x = 30, y = 35;

    printf("%d\n", add<int>(x, y));
    printf("%c\n", add<char>(x, y)); // 文字「A」を返すように強制する

    return(0);
}

汎用クラス(クラステンプレート)

汎用クラスとは

汎用クラスとは、テンプレートを利用して作成した「メンバの型が実行時に定まるクラス」です。

1つのクラスを様々なデータ型に適用できるため、型ごとにクラスを作成する必要がなくなります。


汎用クラスの作成

テンプレートを用いることで汎用クラスを定義することができます。

汎用クラスを作成するには、「template」キーワードを用いてクラスを定義します。


template <class T> class クラス名{ ... };

なお、汎用クラスに存在するメンバ関数はすべて汎用関数となります。

汎用クラスのインスタンスを生成する場合には、以下の形式で型を指定します。


クラス名<型> インスタンス名

クラステンプレートでstackプログラム

クラスstackは、あらゆるデータ型のスタックを実現します。

以下では、数値と文字列をスタック操作しています。


#include <iostream>

template <class T> class stack {
private:
    T buffer[64];  // stack用バッファ
    int index;
public:
    bool push(T var) {
        if(index > 63) return(false);
        buffer[index++] = var;
        return(true);
    }
    T pop(){
        if(index == 0) return(NULL);
        return(buffer[--index]);
    }
    stack(){ index = 0; }
};

int main()
{
    stack<int> num_stack;      // 数値スタック
    num_stack.push(3);
    num_stack.push(5);
    printf("%d\n", num_stack.pop());
    printf("%d\n", num_stack.pop());

    stack<char *> str_stack;    // 文字列スタック
    str_stack.push("template");
    str_stack.push("stack");
    printf("%s\n", str_stack.pop());
    printf("%s\n", str_stack.pop());

    return(0);
}

関連ページ