本記事で使用している環境は以下です。
・Ubuntu 24.04 LTS
・C++17
テンプレート関数とは
C++のテンプレート機能とは、処理を共通化するための型をパラメータ化する機能です。テンプレートには、クラステンプレートと関数テンプレートがありますが、この記事では関数テンプレートについて紹介します。
関数テンプレートを使用すると、同じ関数のコードを異なるデータ型に対して再利用できるようになります。それにより、コードの重複を避け、より汎用的で保守しやすいプログラムを作成できます。
使い方
テンプレート関数の基本的な使い方について、いくつかの例を使って紹介します。
値の比較
#include <iostream>
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
int main() {
int i1 = 42, i2 = 76;
double d1 = 3.14, d2 = 2.71;
std::string s1 = "apple", s2 = "orange";
std::cout << "max(i1, i2) = " << max(i1, i2) << std::endl; // 整数の比較
std::cout << "max(d1, d2) = " << max(d1, d2) << std::endl; // 浮動小数点数の比較
return 0;
}
上のコードでは、max
関数を使って、異なる型の値を比較することができます。1つの関数で整数、浮動小数点数など、異なる型の比較を行うことができます。
解説
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
上記の部分でテンプレート関数max
を定義しています。この例では、max
関数が任意の型T
の引数を2つ受け取り、最大値を返します。template <typename T>
の部分がテンプレートの宣言であり、T
はテンプレートパラメータです。このパラメータは、関数が呼び出される際に具体的な型に置き換えられます。
非型テンプレートパラメータ
#include <iostream>
template <typename T, int size>
void printArray(T (&array)[size]) {
for (int i = 0; i < size; ++i) {
std::cout << array[i] << " ";
}
std::cout << std::endl;
}
int main() {
int intArray[] = {1, 2, 3, 4, 5};
double doubleArray[] = {1.1, 2.2, 3.3, 4.4};
printArray(intArray); // int配列の出力
printArray(doubleArray); // double配列の出力
return 0;
}
テンプレート関数には、型以外のテンプレートパラメータを使用することもできます。上記は配列のサイズをテンプレートパラメータとして渡す例です。この例では、任意の型とサイズの配列を出力することができます。
解説
template <typename T, int size>
void printArray(T (&array)[size]) {
for (int i = 0; i < size; ++i) {
std::cout << array[i] << " ";
}
std::cout << std::endl;
}
この部分でテンプレート関数printArray
を定義しています。T
は型パラメータで、size
は非型テンプレートパラメータ(整数値)です。
void printArray(T (&array)[size])
この行は関数のシグネチャを示しています。T (&array)[size]
は、T
型の要素を持つサイズsize
の配列への参照を受け取ることを意味します。配列を参照渡しすることで、配列のコピーを避けます。
テンプレートの特化
#include <iostream>
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
// int型に特化したテンプレート関数
template <>
int max<int>(int a, int b) {
std::cout << "Specialized version for int called" << std::endl;
return (a > b) ? a : b;
}
int main() {
int i1 = 42, i2 = 76;
double d1 = 3.14, d2 = 2.71;
std::cout << "max(i1, i2) = " << max(i1, i2) << std::endl; // int型の特化バージョンが呼ばれる
std::cout << "max(d1, d2) = " << max(d1, d2) << std::endl; // 汎用バージョンが呼ばれる
return 0;
}
テンプレート関数は特定の型に対して特殊化(特化)することもできます。この例では、int
型の引数に対して特化したmax
関数と汎用的なmax
関数を使い分けています。テンプレート関数の特化を使用することで、汎用版よりも高速な処理を実現したり、特定の型に対して追加のロジックを実装できたりします。
解説
template <>
int max<int>(int a, int b) {
std::cout << "Specialized version for int called" << std::endl;
return (a > b) ? a : b;
}
この部分で、int
型に特化したテンプレート関数を定義しています。int
型を引数にしてmax
関数を読んだ場合にはこのテンプレート関数が使用されます。
最後に
今回はC++のテンプレート関数を紹介しました。テンプレート関数は、同じコードを異なる型に対して再利用できる便利な機能です。テンプレート関数を使用することで汎用的で効率的なプログラムを作成することができます。