記事ディレクトリ
関数本体が同じ関数の場合、関数テンプレートを使用して解決できるのは、パラメータータイプが異なる関数のみですこれは、C ++の汎用プログラミングです。
1関数テンプレート
関数テンプレートは、さまざまなタイプで呼び出すことができる特別な関数です。
1.1関数テンプレートの構文規則
- テンプレートキーワードは、一般的なプログラミングの開始を宣言するために使用されます
- typenameキーワードは、一般的なプログラミングを宣言するために使用されます
1.2関数テンプレートの使用
- 自動型推論呼び出し
- 特定のタイプの表示呼び出し
使用方法は次のとおりです。
プログラミング実験:テンプレート関数の予備調査
// 42-1.cpp
#include<iostream>
#include<string>
using namespace std;
template<typename T>
void Swap(T& a, T& b)
{
T c = a;
a = b;
b = c;
}
template<typename T>
void Sort(T a[], int len)
{
for (int i = 0; i < len; i++)
{
for (int j = i; j < len; j++)
{
if (a[i] > a[j])
{
Swap(a[i], a[j]);
}
}
}
}
template<typename T>
void print(T a[], int len)
{
for (int i = 0; i < len; i++)
{
cout << a[i] << ", ";
}
cout << endl;
}
int main()
{
int a[5] = {4, 5, 1, 3, 2};
Sort(a, 5);
print(a, 5);
string s[5] = {"Java", "C++", "Go", "Python", "C"};
Sort(s, 5);
print(s, 5);
return 0;
}
$ g++ 42-1.cpp -o 42-1
$ ./42-1
1, 2, 3, 4, 5,
C, C++, Go, Java, Python,
2関数テンプレートの本質
コンパイラーは関数テンプレートを2回コンパイルします
- テンプレート自体をコンパイルする
- パラメータ置換後にコードをコンパイルします
注:関数テンプレート自体は暗黙的な型変換を許可していません
- タイプを自動的に導出する場合、厳密に一致させる必要があります
- 表示タイプを指定すると、暗黙的なタイプ変換を行うことができます
プログラミング実験:関数テンプレートの本質
// 42-2.cpp
#include<iostream>
using namespace std;
class Test
{
Test(const Test&);
public:
Test()
{
}
};
template<typename T>
void Swap(T& a, T& b)
{
T c = a;
a = b;
b = c;
}
// 使用typedef定义函数类型
typedef void(FuncI)(int&, int&);
typedef void(FuncD)(double&, double&);
typedef void(FuncT)(Test&, Test&);
int main()
{
FuncI* pi = Swap;
FuncD* pd = Swap;
//FuncT* pt = Swap;
cout << "pi = " << reinterpret_cast<void*>(pi) << endl;
cout << "pd = " << reinterpret_cast<void*>(pd) << endl;
//cout << "pt = " << reinterpret_cast<void*>(pt) << endl;
return 0;
}
- typedefを使用して3つの関数タイプを定義します。関数テンプレートコンパイラは1回コンパイルする必要があり、パラメータ置換後のコードも1回コンパイルする必要があります。25行目と26行目では、2つのポインタが2つの特定の関数を指しています。
- クラスTestのコピーコンストラクターはプライベートとして定義されていますが、特定のコードを生成すると、プライベートコンストラクターは割り当てを完了できず、コンパイルエラーが発生します。コンパイラーがテンプレート自体をコンパイルする必要があること、および置き換えられたコードもコンパイルする必要があることが再度確認されます。
コンパイルして実行
$ g++ 42-2.cpp -o 42-2
$ ./42-2
pi = 0x55daa8490a01
pd = 0x55daa8490a2e
関数ポインタのアドレスが異なることがわかります。
3マルチパラメーター関数テンプレート
- 関数テンプレートは、さまざまなタイプのパラメーターをいくつでも定義できます
マルチパラメーター関数テンプレートの場合
- 戻り値の型を自動的に導出することはできません
- 型パラメーターは左から右に指定できます
プロジェクトの最初のタイプパラメータとしての戻り値パラメータ
プログラミング実験:マルチパラメーター関数テンプレート
// 42-3.cpp
#include<iostream>
using namespace std;
template<typename T1, typename T2, typename T3>
T1 add(T2 a, T3 b)
{
return static_cast<T1>(a + b);
}
int main()
{
int r1 = add<int>(0.5, 0.8);
double r2 = add<double, float>(0.5, 0.8);
float r3 = add<float, float, float>(0.5, 0.8);
cout << "r1 = " << r1 << endl;
cout << "r2 = " << r2 << endl;
cout << "r3 = " << r3 << endl;
return 0;
}
- 最初のパラメータを使用して戻り値のタイプを指定します。r1を解くとき、T1はint、T2はdouble、T3はdoubleです
- r2を解くとき、T1はdouble、T2はfloat、T3はdoubleです。
- r2を解くとき、T1は浮動小数点数、T2は浮動小数点数、T3は浮動小数点数
$ g++ 42-3.cpp -o 42-3
$ ./42-3
r1 = 1
r2 = 1.3
r3 = 1.3
4関数テンプレートは関数のオーバーロードに対応
関数テンプレートは通常の関数のようにオーバーロードできます
- 通常の機能を優先する
- 関数テンプレートがより適切な一致を生成できる場合は、テンプレートを選択します
- 空のテンプレート引数リストを持つテンプレートのみに一致するようにコンパイラーを制限できます
// 42-3.cpp
#include<iostream>
using namespace std;
template<typename T>
T MAX(T a, T b)
{
cout << "T MAX(T a, T b)" << endl;
return a > b ? a : b;
}
int MAX(int a, int b)
{
cout << "int MAX(int a, int b)" << endl;
return a > b ? a : b;
}
template<typename T>
T MAX(T a, T b, T c)
{
cout << "T MAX(T a, T b, T c)" << endl;
return MAX(MAX(a, b), c);
}
int main()
{
int a = 1;
int b = 2;
cout << MAX(a, b) << endl << endl; // 普通函数 MAX(int, int)
cout << MAX<>(a, b) << endl << endl; // 函数模板 MAX<int>(int, int)
cout << MAX(3.0, 4.0) << endl << endl; // 函数模板 MAX<double>(double, double)
cout << MAX(5.0, 6.0, 7.0) << endl << endl; // 函数模板 MAX<double>(double, double, double)
cout << MAX('a', 70) << endl << endl; // 普通函数 MAX(int, int)
return 0;
}
優先度は通常の関数に与えられます。関数テンプレートがより一致する場合、テンプレートが選択されます。空のテンプレート引数リストを使用して、テンプレートのみに一致させることもできます
コンパイルして実行
$ g++ 42-4.cpp -o 42-4
$ ./42-4
int MAX(int a, int b)
2
T MAX(T a, T b)
2
T MAX(T a, T b)
4
T MAX(T a, T b, T c)
T MAX(T a, T b)
T MAX(T a, T b)
7
int MAX(int a, int b)
97
5まとめ
1.関数テンプレートは、実際のパラメーターに従ってパラメータータイプを
推定できます。2 . 自動的にタイプを推定して呼び出すことができます。また、指定されたパラメータータイプを表示することもできます。3.
関数テンプレートは、特定のタイプごとに異なる関数を生成します
。4.コールドテンプレートは、複数の異なるタイプパラメーターを定義できます
5.関数テンプレートはオーバーロード可能