関数テンプレートとは?
- 関数テンプレート関数とは変数の型がコンパイル時に決定されるものです。
- 例えば、int型・double型の1次元ベクトルvecを表示する関数を関数テンプレートを使わずに作ると次のようになります。
// int型の1次元vectorを表示する関数 void printVectorInt(std::vector<int> vec) { std::cout << "vec = { "; for (int a : vec) { std::cout << a << ", "; } std::cout << "}" << std::endl; } // double型の1次元vectorを表示する関数 void printVectorDouble(std::vector<double> vec) { std::cout << "vec = { "; for (double a : vec) { std::cout << a << ", "; } std::cout << "}" << std::endl; }
- この場合、string型も表示・カンマ区切りではなくスペース区切りの表示へ変更するなどプログラムを少しいじるだけでも変更点が多くて面倒です。
- このような場合に、変数の型だけ違う複数の関数を1つにできるのがテンプレート関数です。
基本形1(関数の中で任意の型名を使用)
関数テンプレートの宣言
- int・doubleなど関数内で可変にしたい型名は任意の名称に置き換えます。
- これをTとする場合は、 template < typename T >で宣言します。
- 例)Tのサイズを返す関数
template<typename T> int sizeT() { int sizeT = sizeof(T); return sizeT; }
関数テンプレートの呼び出し
- 呼び出しの際にTの型名を与えます。
- 例)先ほどの関数をT=intで実行。
int a = sizeT<int>();
実装例
ソースコード
#include<iostream> #include<vector> // Tのサイズを返す template<typename T> int sizeT() { int sizeT = sizeof(T); return sizeT; } int main(void) { // int型のサイズを取得 std::cout << "sizeT<int>() = " << sizeT<int>() << std::endl; // double型のサイズを取得 std::cout << "sizeT<double>() = " << sizeT<double>() << std::endl; }
実行結果
sizeT<int>() = 4 sizeT<double>() = 8
基本形2(引数の型名が任意)
関数テンプレートの宣言
- 宣言の仕方は基本的に先ほどと同じ。
- 例) 最初に例に挙げた1次元配列を表示する関数。
template<typename T> void printVector(std::vector<T> vec) { std::cout << "vec = { "; for (T a : vec) { std::cout << a << ", "; } std::cout << "}" << std::endl; }
関数テンプレートの呼び出し
- 引数にTが含まれている場合は、Tの指定が不要(引数で指定したとみなせるため)。
- そのため、普通の関数と同様にして呼び出せます。
std::vector<int> a{ 1, 2, 3 }; printVector(a);
実装例
ソースコード
#include<iostream> #include<vector> template<typename T> void printVector(std::vector<T> vec) { std::cout << "vec = { "; for (T a : vec) { std::cout << a << ", "; } std::cout << "}" << std::endl; } int main(void) { // int型vectorの表示 std::vector<int> a{ 1, 2, 3 }; printVector(a); // double型vectorの表示 std::vector<double> b{ 1.0, 1.5, 2.5 }; printVector(b); }
実行結果
vec = { 1, 2, 3, } vec = { 1, 1.5, 2.5, }
基本形3(返り値の型が任意)
- 返り値の型をTにすればOKです。
ソースコード
#include<iostream> #include<vector> template<typename T> T sum(const std::vector<T>& vec) { T result = 0; for (const T& a : vec) { result += a; } return result; } int main(void) { // int型vectorの表示 std::vector<int> a{ 1, 2, 3 }; std::cout << sum(a) << std::endl; // double型vectorの表示 std::vector<double> b{ 1.0, 1.5, 2.5 }; std::cout << sum(b) << std::endl; }
実行結果
6 5
実装例1(2つ以上の任意の型名を使用)
- 使用する型をカンマ区切りで指定すればOKです。
ソースコード
#include<iostream> // 2つの変数を出力 template<typename T1, typename T2> void printAB(T1 A, T2 B) { std::cout << "A = " << A << ", B = " << B << std::endl; } int main(void) { printAB("str", 2); printAB(3.5, 'c'); }
実行結果
A = str, B = 2 A = 3.5, B = c