テンプレートプログラミングの基礎

1. ジェネリックプログラミングとは

異なる型の変数を交換する関数を実装する際、通常は次のように型ごとに関数を用意します:


void swap(int& a, int& b) {
    int tmp = a;
    a = b;
    b = tmp;
}

void swap(double& a, double& b) {
    double tmp = a;
    a = b;
    b = tmp;
}

しかし、このような関数オーバーロードには以下のような問題があります:

  • 型が異なるだけでコードの構造が同じため、再利用性が低い
  • 新しい型が追加されるたびに新しい関数を実装する必要がある
  • 保守性が低く、1つの関数にバグがあると全関数に影響する可能性がある

C++では、このような作業を効率化するための仕組みとしてテンプレートが提供されています。テンプレートは「設計図」のようなもので、異なる型を「材料」として使い、必要なコードを自動生成します。

2. 関数テンプレート

概念

関数テンプレートは、型に依存しない関数の設計図です。呼び出される際に型パラメータを指定することで、その型に応じた関数がコンパイラによって自動生成されます。

基本構文


template<typename T>
戻り値 型関数名(T& a, T& b) {
    // 関数の処理
}

例:swap関数のテンプレート化


template<typename T>
void swap(T& a, T& b) {
    T tmp = a;
    a = b;
    b = tmp;
}

この関数は、int、double、charなど、あらゆる型で動作します:


int main() {
    int x = 10, y = 20;
    swap(x, y); // int型での使用

    double a = 3.14, b = 2.71;
    swap(a, b); // double型での使用
}

インスタンス化の種類

  • 暗黙的インスタンス化: コンパイラが引数の型から自動推論
  • 明示的インスタンス化: 呼び出し時に型を明示指定

// 暗黙的インスタンス化
swap(x, y); // Tはintと推論

// 明示的インスタンス化
swap<double>(a, b);

通常関数とテンプレート関数の優先順位

同じ名前の通常関数とテンプレート関数が存在する場合、通常関数が優先的に呼び出されます。ただし、テンプレートがより適切な引数型を持つ場合は、テンプレート関数が選択されます。


int add(int a, int b) {
    return a + b;
}

template<typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    add(1, 2); // add(int, int)が呼ばれる
    add<double>(1.0, 2.0); // add<double>(double, double)が呼ばれる
}

3. クラステンプレート

定義の構文


template<class T>
class クラス名 {
    // メンバーの定義
};

例:Stackクラスのテンプレート化


template<class T>
class Stack {
public:
    void push(const T& value);
private:
    T* data_;
    int top_;
    int capacity_;
};

template<class T>
void Stack<T>::push(const T& value) {
    // メンバー関数の実装
}

クラスのインスタンス化

クラステンプレートは、使用する際に型を指定してインスタンス化する必要があります:


Stack<int> intStack;   // int型のスタック
Stack<double> dblStack; // double型のスタック

関数テンプレートとは異なり、クラステンプレートはテンプレート引数を明示的に指定する必要があるため、自動推論は行われません。

typedefとの比較

  • typedefは特定の型を別名で定義できるが、複数の型を扱うには不向き
  • クラステンプレートは、複数の型に対応した汎用的なクラスを定義できる
  • テンプレートの定義と実装を分離する際にはテンプレートパラメータを明示する必要があるため、通常はヘッダファイル内にすべてを記述する

タグ: C++ テンプレート ジェネリックプログラミング 関数テンプレート クラステンプレート

6月23日 21:09 投稿