C++のテンプレートとは、「型に依存しない」プログラムを作るための仕組みです。同じ処理を int 型、double 型、string 型などで繰り返し書く必要がなくなります。
まずは、型ごとに異なる関数を作る代わりに、テンプレートを使う例を見てみましょう。
// 21_template_basic.cpp
#include <iostream>
#include <string>
using namespace std;
// 型に依存しないテンプレート関数
template <typename T>
void showValue(T value) {
cout << "値: " << value << endl;
}
int main() {
showValue(10); // int型
showValue(3.14); // double型
showValue('A'); // char型
showValue(string("Hi")); // string型
return 0;
}
template <typename T> では、T は「型の変数」であり、呼び出すときの実際の型に応じて自動的に置き換わります。
showValue(10); では T は int 型showValue(3.14); では T は double 型出力結果(例)
値: 10 値: 3.14 値: A 値: Hi
関数だけでなく、クラスにもテンプレートを使うことができます。「型を入れ替えられるクラス」を作ることで、汎用的なデータ構造を実現できます。
// 21_template_class.cpp
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class Box {
private:
T value; // 保持する値
public:
// コンストラクタ:初期値を受け取る
Box(T initialValue) : value(initialValue) {}
void show() {
cout << "Boxの中身: " << value << endl;
}
};
int main() {
Box<int> intBox(123); // int型のBox
Box<double> dblBox(4.56); // double型のBox
Box<char> charBox('X'); // char型のBox
Box<string> strBox("Hello"); // string型のBox
intBox.show();
dblBox.show();
charBox.show();
strBox.show();
return 0;
}
出力結果(例)
Boxの中身: 123 Boxの中身: 4.56 Boxの中身: X Boxの中身: Hello
| メリット | 内容 |
|---|---|
| 再利用性 | 型ごとに同じ処理を繰り返し書かなくてよい |
| 保守性 | コードを1か所修正すれば全型に反映される |
| 可読性 | 「何をしているクラス・関数か」が明確になる |
テンプレートは、ゲーム開発でも便利です。例えば「スコア」「HP」「MP」など、さまざまな型の値を管理する共通クラスを作れます。
// 21_game_status_template.cpp
#include <iostream>
using namespace std;
template <typename T>
class Status {
private:
T value;
public:
Status(T v) : value(v) {}
void set(T v) { value = v; }
T get() { return value; }
};
int main() {
Status<int> hp(100); // HP(整数)
Status<double> mp(35.5); // MP(小数)
cout << "HP: " << hp.get() << endl;
cout << "MP: " << mp.get() << endl;
return 0;
}
実行結果(例)
HP: 100 MP: 35.5
次のコードの出力を考えてみましょう(21_check_template.cpp)。
#include <iostream>
using namespace std;
template <typename T>
T multiply(T a, T b) {
return a * b;
}
int main() {
cout << multiply<int>(2, 3) << endl;
cout << multiply<double>(1.5, 2.0) << endl;
return 0;
}
6 3
maxValue(T a, T b) を作成し、大きい方の値を返すようにせよ。int と double で試し、正しい値が返ることを確認せよ。// 21_template_practice.cpp
#include <iostream>
using namespace std;
template <typename T>
T maxValue(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << maxValue<int>(10, 20) << endl; // 20
cout << maxValue<double>(2.5, 1.8) << endl; // 2.5
return 0;
}
showValue のコードを入力して実行しましょう。int・double・char・string の4種類の型で動作を確認してください。
21_01_Template の 21_template_basic.cpp をコピーして 21_02_TemplateMod に貼り付け、次の変更を加えてみましょう:
addValues(T a, T b) を追加し、2つの値の和を返すBox クラステンプレートを追加し、get() と set() メソッドも実装するtemplate <typename T> で型に依存しないコードを書ける次のテンプレート関数 multiply<int>(3, 4) を呼び出したとき、戻り値はどれか。
template <typename T>
T multiply(T a, T b) { return a * b; }
T が int になるので 3 * 4 = 12 が返る。テンプレートはコンパイル時に型が確定し、int multiply(int a, int b) として展開される。
クラステンプレートを使って Box<double> b(3.14); と宣言したとき、T の型はどれか。
Box<double> と指定しているので T = double。テンプレートの型引数は <> の中に明示する。
次のコードの出力として正しいものはどれか。
template <typename T>
T maxVal(T a, T b) { return (a > b) ? a : b; }
int main() {
cout << maxVal<int>(5, 3) << endl;
cout << maxVal<double>(2.1, 4.9) << endl;
}
maxVal<int>(5, 3) は 5 を返す(5 > 3)。maxVal<double>(2.1, 4.9) は 4.9 を返す(4.9 > 2.1)。テンプレートは型に応じて正しく動作する。
テンプレートを使う目的として最も不適切なものはどれか。