English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C++テンプレート関数の詳細な説明

C++テンプレートは主に以下の二つのカテゴリに分類されます:テンプレート関数、テンプレートクラス。この記事ではまずテンプレート関数について書き、次にテンプレートクラスについて紹介します。

定義:テンプレート関数は一般的な関数の記述であり、一般的なタイプを使用して定義されます。その一般的なタイプは、具体的なタイプで置き換えられます。

コード例:

#include <iostream>
//テンプレートクラスの宣言
template<typename T>
void Swap(T& a,T& b);
int main()
{
  int i = 10;
  int j = 20;
  std::cout<<"i=" << i << "," << "j=" <<j;
  Swap(i,j);//void Swap(int &,int&);
  std::cout<<"i=" << i << "," << "j=" <<j;
  double x = 11.5;
  double y = 19.5;
  std::cout<<"x=" << x << "," << "y=" <<y;
  Swap(x,y);//コンパイラが生成する void Swap(double &,double&);
  std::cout<<"x=" << x << "," << "y=" <<y;
  return 0;
}
//テンプレートクラスの定義
template<typename T>
void Swap(T& a,T& b)
{
  T temp;
  temp = a;
  a = b;
  b = temp;
}

上記の例は最も単純な関数テンプレートの例です。コンパイラは実際に使用されるタイプに応じて、対応する関数を生成します。

オーバーロードされたテンプレート:

異なるタイプに対して同じアルゴリズムを使用する必要がある場合、テンプレートを使用できます。上記のコードのように、すべてのタイプが同じアルゴリズムを使用するわけではありません。このようなニーズを満たすために、通常の関数のオーバーロードと同様にテンプレートのオーバーロードを使用できます。オーバーロード関数と同様に、オーバーロード関数の特徴表は異ななければなりません。以下にコード例を示します:

#include <iostream>
//テンプレートクラスの宣言
template<typename T>
void Swap(T& a,T& b);
const int iCount = 5;
template<typename T>
void Swap(T* a,T*b,int n);
int main()
{
  int i = 10;
  int j = 20;
  std::cout<<"i=" << i << "," << "j=" <<j;
  Swap(i,j);//void Swap(int &,int&)
  std::cout<<"i=" << i << "," << "j=" <<j;
  double x = 11.5;
  double y = 19.5;
  std::cout<<"x=" << x << "," << "y=" <<y;
  Swap(x,y);//コンパイラが生成する void Swap(double &,double&);
  std::cout<<"x=" << x << "," << "y=" <<y;
  int d[iCount] = {0,1,2,3,4};
  int e[iCount] = {5,6,7,8,9};
  Swap(d,e,iCount);//新しいテンプレートにマッチし、配列の交換を行います
  return 0;
}
//テンプレートクラスの定義
template<typename T>
void Swap(T& a,T& b)
{
  T temp;
  temp = a;
  a = b;
  b = temp;
}
template<typename T>
void Swap(T* a,T*b,int n)
{
  for (int i=0;i<iCount;++i)
  {
    T temp;
    temp = a[i];
    a[i] = b[i];
    b[i] = temp;
  }
}

上記のコードでは、2つの配列の要素を交換するための新しいテンプレートが追加されました。元のテンプレートの特徴は(T&,T&)であり、新しいテンプレートの特徴は(T[],T[]),int)です。最後のテンプレートでは、最後の引数のタイプは具体的なタイプ(int)であり、一般的なタイプではありません。すべてのテンプレート引数がテンプレートのタイプでない必要はありません。

表示具体的な:

特定の関数名に対して、非テンプレート関数、テンプレート関数および表示具体的なテンプレート関数およびそれらのオーバーロードバージョンが存在できます。

表示具体的なプロトタイプおよび定義はtemplate<>で先頭に付け、名前でタイプを指摘する必要があります。

具体的な実装は通常のテンプレートを覆し、非テンプレート関数は具体的な実装および通常のテンプレートを覆します。

以下は、Job構造体を交換するための非テンプレート関数、テンプレート関数および具体的な実装のプロトタイプです。

void Swap(job &,job&);//非テンプレート関数
template <typename T>
void Swap(T&,T&);//テンプレート関数
template <> void Swap<job>(job&,job&);//表示具体的な関数、Swapの後のjob引数を削除できる場合、関数のシグネチャはtemplate <> void Swap(job&,job&);となります。

前面指摘、複数のプロトタイプがある場合、コンパイラがプロトタイプを選択する際には、非テンプレートがテンプレートの具体的な実装よりも優先され、具体的な実装がテンプレート生成のバージョンよりも優先されます。

以下のような呼び出し:

double u, v;
Swap(u, v);//一般的なテンプレートを使用します。
job a, b;
swap(a, b)//表示具体化のバージョンを使用します。

インスタンス化和具体化:

    テンプレートについてさらに理解するために、インスタンス化と具体化の用語を理解する必要があります。覚えておいてください、コードに関数テンプレートを含むだけで、関数の定義は生成されません。それは、関数定義を生成するためのスキーマに過ぎません。コンパイラが特定の型にテンプレートを使用して定義を生成するとき、それはテンプレートインスタンス(instantiation)です。例えば、Swap(i, j)という関数呼び出しは、コンパイラがSwap()のインスタンスを生成し、int型を使用します。テンプレートは関数定義ではありませんが、intを使用するテンプレートインスタンスは関数定義です。このインスタンス化方法は、コンパイラがintパラメータを提供するSwap()呼び出し時に定義が必要であることを知るための暗黙的なインスタンス化と呼ばれます。

    現在、コンパイラは表示例示を許可することで、特定のインスタンスを直接生成するコマンドを与えることができます。その構文は、選択した種類の宣言です-型を<>で示し、宣言の前にtemplateキーワードを付ける:

template void Swap<int>(int, int);;//表示例示

この特性を実装したコンパイラは、上記の宣言を見た後、int型のインスタンスを生成するSwap() テンプレートを使用します。

表示例示とは異なり、表示具体化は以下の二つの等価な宣言のうちのいずれかを使用します:

template <> void Swap<int>(int, int);
template <> void Swap(int, int);

違いは、以下の意味です「Swap() テンプレートを使用して関数定義を作成しないでください。代わりに、独立した、特別な関数定義をint型で生成するようにしてください」

注意:同じ種類の表示具体化と表示例示を使用してプログラミングユニットでエラーが発生します。

以上は、編集者が皆さんに紹介したC++以下の説明は、皆さんに役立つことを願っています。何か疑問があれば、コメントを残してください。

基礎教程
おすすめ