templateの実装をヘッダファイルに書かないでcppファイルに書く際の書き方まとめ

templateを使った関数なりの実装をヘッダに書くのはごちゃごちゃして嫌なんでcppに書いておきたいですよと。
ただコンパイル時にきちんと所望の型で関数・クラスがテンプレートから作成されるようにcppファイルの方で明示的に実体化しておかないといけませんよと。

その際、名前空間・クラス・テンプレート関数でそれぞれちょっと書き方が違うのでメモ代わりにまとめておく。

main.cpp

#include <iostream>
#include "Templates.h"

int main()
{
	std::cout << Add<int>(1, 2) << std::endl;
	std::cout << MySpace::Add(1, 2) << std::endl;
	std::cout << MyClass1::Add(1, 2) << std::endl;
	std::cout << MyClass2<int>::Add(1, 2) << std::endl;
	MyClass3<int> x;
	std::cout << x.Add(1, 2) << std::endl;
	
	return 0;
}

Templates.h

#ifndef __TEMPLATESH__
#define __TEMPLATESH__
//-------------- 宣言 ----------------//
//関数版
template <class T> T Add(T x, T y);
//クラス版
class MyClass1
{
public : 
	template <class T> static T Add(T x, T y);
};
template <class T>
class MyClass2
{
public : 
	static T Add(T x, T y);
};
template <class T>
class MyClass3
{
public : 
	T Add(T x, T y);
};
//名前空間版
namespace MySpace
{
	template <class T> T Add(T x, T y);
}
#endif

Templates.cpp

#include "Templates.h"
//-------------- 実装 ----------------//
//関数版
template <class T>
T Add(T x, T y)
{
	return x + y;
}
//クラス版
template <class T>
T MyClass1::Add(T x, T y)
{
	return x + y;
}
template <class T>
T MyClass2<T>::Add(T x, T y)
{
	return x + y;
}
template <class T>
T MyClass3<T>::Add(T x, T y)
{
	return x + y;
}
//名前空間版
namespace MySpace
{
	template <class T>
	T Add(T x, T y)
	{
		return x + y;
	}
}
//-------------- 実体化 ----------------//
//関数版
template int Add<int>(int x, int y);
//クラス版
template int MyClass1::Add<int>(int x, int y);
template int MyClass2<int>::Add(int x, int y);
template int MyClass3<int>::Add(int x, int y);
//名前空間晩
template int MySpace::Add<int>(int x, int y);