テンプレートの使用方法

#C++テンプレートの使用方法

#はじめに
Qiitaへの投稿は初めてですが初めての投稿なので思ったより製作に時間がかかりました。
初めての投稿なのでよろしくです('ω')ノ
いろいろ調べて分かったことなどを自分なりにわかりやすく解説していきます。
たくさん不備があると思いますが半分自分用なのでご了承願います(*- -)
それでは、サラダバー。

※コンストラクタテンプレートには触れていませんが必要になれば追加します。


##テンプレートの種類
1.関数テンプレート
2.クラステンプレート
3.メンバテンプレート
4.エイリアステンプレート

##テンプレートの定義

```c++:template.cpp
template<class datatype>
```

###tips

`template<class datatype_1>`と`template<typename datatype_1>`の意味は同じ

####テンプレート引数は複数個作れる

```c++:template.cpp
template<class datatype_1, class datatype_2, ...>
```

##関数テンプレート
```c++:template.h
template<class datatype>
void add(datatype* x, datatype y){
   *x + y;
}
```

##クラステンプレート
```c++:template.h
template<class datatype>
class Temp{

public:
   datatype x;
   datatype y;

}
```

##メンバテンプレート
```c++:template.h
class Temp{

public:
   template<class datatype>
   void ShowData(datatype x){
      std::cout << x << endl;
   }

}
```

##エイリアステンプレート
```c++:template.h

template<typename datatype_1,typename datatype_2>
datatype_1 Add(datatype_1 a,datatype_2 b);

template <typename X>
using _Add = Add<X,X>;

```
**エイリアステンプレートはテンプレート関数名とテンプレート引数の変更が可能**

これで基本的なテンプレートは全て実装できました
ただ、この後に出てくる関数の実装が少し厄介です。

##関数テンプレート・クラステンプレート・メンバテンプレートの関数の実装

テンプレートの関数の実装方法は下記に説明する三種類の方法があります

1.クラス内にインライン関数として実装（クラステンプレート・メンバテンプレートのみ）
2.関数テンプレート・クラステンプレート・メンバテンプレートの**関数を定義したファイル内**に実装する
※関数テンプレートは関数の実装のみでもOK
3.ファイル分けをする場合は、**予め使われる型を使って明示的実体化**を行っておく
※**明示的実体化を行っていない型を使用するとリンカーエラー**

###1.インライン関数として実装
```c++:template.h
template<class datatype>
class Temp{

public:
   datatype x;
   datatype y;

   //コンストラクタのインライン関数
   Temp(){
      x = 0;
      y = 0;
   }

}
```

###2.同じファイル内に関数を実装
```c++:template.h

template<class datatype>
void add(datatype* x, datatype y);

template<class datatype>
class Temp{

public:
   datatype x;
   datatype y;

   //コンストラクタ
   Temp();

}

//コンストラクタ
template<class datatype>
Temp<datatype>::Temp(){

   this->x = 0;
   this->y = 0;

}


template<class datatype>
void add(datatype* x, datatype y){
   *x + y;
}
```

###3.ファイルを分けて関数を実装
```c++:template.h

template<class datatype>
void add(datatype* x, datatype y);

template<class datatype>
class Temp{

public:
   datatype x;
   datatype y;

   //コンストラクタ
   Temp();

}
```
```c++:template.cpp
//--明示的実体化--//

template class Temp<int>;
template class Temp<double>;

//--明示的実体化--//

//コンストラクタ
template<class datatype>
Temp<datatype>::Temp(){

   this->x = 0;
   this->y = 0;

}


template<class datatype>
void add(datatype* x, datatype y){
   *x + y;
}
```

```c++:main.cpp

#include"template.h"

int main(){

   //クラス宣言時　
   //クラス名<使用するデータ型>オブジェクト名
   Temp <int>temp

   add(temp.x, temp.y);

}
```

#テンプレート別の明示的実体化記述方法
```cpp:template.cpp

//関数テンプレートの明示的実体化の記述法
//template␣戻り値型␣関数名(関数の引数)
template int func(int x);

//クラステンプレートの明示的実体化の記述法
//template class␣クラス名<使用するデータ型>
template class Temp<int>

//クラステンプレート内関数・メンバテンプレート関数の明示的実体化の記述法
//template␣戻り値型␣クラス名<使用するデータ型>::関数名(関数の引数)
template int Temp<int>::func(int x);

//--クラステンプレート内のメンバテンプレート関数--//

//クラステンプレート内のメンバテンプレート関数の明示的実体化
//template␣戻り値型␣クラス名<使用するデータ型>::関数名(関数の引数)
template void Temp<int>::func(int);

//クラステンプレート内のメンバテンプレート関数の実装時の記述方法
template<"クラステンプレートのテンプレート引数">   //どちらも記述しないとエラー
template<"メンバテンプレートのテンプレート引数">   //どちらも記述しないとエラー
//関数の実装部分はメンバ関数の記述方法と同じ
void Temp<class_datatype>::func("メンバ関数の定義時の引数と同じ引数"){}

//--クラステンプレート内のメンバテンプレート関数--//

```