テンプレート

■テンプレート

C++のテンプレートとはクラスのメンバ変数や関数の引数や戻り値を
定義する段階ではあいまいな状態で定義することができる機能です。
プログラムではメンバや関数のアルゴリズムが同じでもデータ型のみを変えたいという
状況が多々あるので、そういった際にこのテンプレート機能を使用することで
汎用的なクラスや関数を作成することができます。

●テンプレート関数の書式
	書式例:
		template <typename パラメータ名> パラメータ名 関数名(引数)
		{
		}

	具体例:
		template <typename T> T AddSum(T x, T y)
		{
			return (x + y);
		}

		void main(void)
		{
			printf("int AddSum(10, 10) => %d\n", AddSum(10, 10));
			printf("float AddSum(20.0f, 20.0f) => %f\n", AddSum(20.0f, 20.0f));
		}

		出力結果:
			int AddSum(10, 10) => 20
			float AddSum(20.0f, 20.0f) => 40.0

	上記の具体例ではAddSumの戻り値、引数にテンプレートパラメータ「T」を使用しています。
	このAddSumは関数定義時点では戻り値、引数のデータ型はあいまいな状態です。
	AddSumのデータ型はmain関数のAddSum関数呼び出しの部分で決まります。
	コンパイラが関数呼び出しの部分を読み取り、設定されているデータ型で
	関数を実行するように対応してくれます。
	テンプレートを使用すると関数のオーバーロードを作成しなくとも
	同様の効果を生み出す処理を作成することができます。

●テンプレートクラスの書式
	書式例:
		定義:
			template <class T>
			class クラス名
			{
				T メンバ変数;

				T 関数名(引数)
				{
				}
			};

		宣言:
			クラス名<データ型> 変数名;
				

	具体例:
		定義:
			template <class T>
			class Position
			{
			public:
				T GetPosX()
				{
					return m_PosX;
				}

				T GetPosY()
				{
					return m_PosY;
				}

				void SetPosX(T posx)
				{
					m_PosX = posx;
				}

				void SetPosY(T posy)
				{
					m_PosY = posy;
				}
			private:
				T m_PosX;
				T m_PosY;
			};

		宣言:
			// メンバをint型として扱う
			Position<int> i_pos;
			// メンバをfloat型として扱う
			Position<float> f_pos;

	クラスは定義に関してはテンプレート関数と同じで、
	templateから始まり、パラメータの指定を行い、
	データ型の定義をあいまいにしたいメンバに対しては
	パラメータをデータ型として使用して宣言を行います。
	テンプレート関数と違い、宣言時に型の指定を行う必要があります。
	宣言するクラス名と変数名の間に、そのクラス変数が使用するデータ型を指定します。
	テンプレートを使用したクラスを汎用クラスと呼ばれています。

●その他
	・typenameとclass
		テンプレート関数の際は<typename パラメータ名>、
		テンプレートクラスはというように
		異なる記述を行っていますが、「typename」「class」の
		どちらを使用しても効果が変わるということはありません。

	・パラメータの数
		テンプレートで設定できるパラメータは1つだけではなく
		複数設定することが可能です。

		例:
			template<typename T, typename U>
			class OriRect
			{
			public:
			private:
				T m_PosX;
				T m_PosY;
				U m_Width;
				U m_Height;
			};

			void main(void)
			{
				OriRect<int, float> rect1;
				OriRect<float, float> rect2;
			}
	
	・パラメータの名前
		パラメータの名前は変数名のように自由に設定することができます。
		参考書などではTが使用されていることがありますが
		これはTemplateのTから来ているといわれています。
		また、パラメータが複数の場合はTの次はUを使用されていることが多く
		これはアルファベットのTの次がUだからです。
		多重forの場合i、j、kと同じように深く考えずに
		こういうものだと考えるといいと思います。

		例:
			template<typename DATA>
			class Position
			{
			public:
			private:
				DATA m_PosX;
				DATA m_PosY;
			};

			void main(void)
			{
				Position<int> pos1;
				Position<float> pos2;
			}

■テンプレートクラスの関数定義(クラス外)

テンプレートクラスの関数定義を行う場合
通常の「クラス名::関数名」で定義することはできません。
定義にはテンプレートクラスであることを明示する必要があります。

●書式
	書式例:
		template <typename パラメータ名>
		戻り値の型 クラス名<パラメータ名>::関数名(引数)
		{
				
		}

	具体例:
		template<typename DATA>
		class Position
		{
		public:
			Position();
		private:
			DATA m_PosX;
			DATA m_PosY;
		};

		tmplate <typename T>
		Position<T>::Position()
		{
			printf("Positionのコンストラクタ\n");
		}