템플릿(Template)

→ (C++에서) 타입에 관계없이 알고리즘을 기술하는 프로그래밍 패러다임이라는 기능을 지원하는 것이다.

템플릿 문법

// 클래스 템플릿 정의하는 법

template <typename(타입의 이름) T>
struct A { T Data; };

// 함수 템플릿 정의하는 법

template <typename(타입의 이름) T>
void Swap(T& lhs, T& rhs) //lhs와 rhs는 변수 이름일 뿐이다.
{
   T temp = lhs;
	 lhs = rhs;
	 rhs = lhs;
}

**Q. 템플릿을 사용하려면?**
→ 매개변수 목록에 인자를 전달하면 된다.
→ 이를 특정 타입(Specific Type)으로 대체한다고 하며
	→ 특수화(Specialization)라고 한다.

A<int> a;
→ a는 int 타입의 Data를 가진다.

A<double> b;
→ b는 double 타입의 Data를 가진다.

**ex)**
int a = 10, b = 20; 
Swap<int, int>(a, b);
Swap(a, b); → **함수 템플릿**은 **<>를 생략**할 수 있다.
**타입 파라미터가 타입을 받을 수 있다**
→
template <typename T> class A {};

template <class T> class B {};
→ **typename** 대신 **class** 를 사용할 수 있다.

template <typename T = int> class C {};
→ 기본 인자 전달도 가능하다. 
→ C<> c; 에서 c는 C<int> 타입이다.

- **비 타입 파라미터**는 **구체적인 타입을 지정**하는 것이다.
- 비 타입 파라미터에 넣을 수 있는 타입
	**1. 정수형** (int)
	**2. 포인터** (pointer)
	**3. 레퍼런스** (reference - 참조)
+ 기본 인자 전달이 가능하다.
→
template <size_t N = 10> struct Array { int Container[N]; };;
template <template<typename> typename Container = Container<int>>
class Temp {};

특수화

template<typename T, size_t N>
struct ObakaArray { T Container[N]; };

ObakaArray<int, 10> arr;
→ 컴파일러 : 컴파일 타임에 아래와 같은 코드를 생성한다.
→ template <>
→ struct ObakaArray { int Container[10]; };

**→ 따라서 일반적으로 템플릿은...** 
		→ 1. 헤더 파일에 모든 내용을 적는다.
			2. 정의를 소스 파일에 나눠서 적으면 링크 오류가 발생한다.

--Temp.h--
template <typename T>
class A
{
public:
	 void SetData(const T& data);
	 T GetData() const;
private:
	 T _data;
};

--Temp.cpp--
→ 이 파일 아래에 있는 템플릿은 인스턴스가 만들어지지 않는다.
template <typename T>
void A<T>::SetData(const T& data)
{
	 _data = data;
}

template <typename T>
T A<T>::GetData() const
{
	 return _data;
}

--Main.cpp--
int main()
{
	 A<int> a;
→ 아래와 같이 인스턴스가 만들어진다.
→ 정의가 없음을 볼 수 있다.

template <>
class A
{
public:
	 void SetData(const int& data);
	 int GetData() const;
private:
	 int _data;
};

a.SetData(10);
→ Link Error! : 정의가 없다.
template <typename T1, typename T2>
void Print(const T1& a, const T2& b)
{
	 std::cout << a << '\\n';
	 std::cout << b << '\\n';
}

**→ 명시적 특수화**
template <>
void Print(const int& a, const double& b)
{
	 std::cout << "명시적으로 특수화 되었다.\\n";
{

**→ 부분 특수화**
template <typename T>
void Print(const T& a, const int& b)
{
	 std::cout << "부분적으로 특수화 되었다.\\n";

double d = 1.0;
Print(d, d); →  Print<double, dobule>; **암시적 특수화 버전 호출**

int i = 1;
Print(i, d); →  Print<int, double>; **명시적 특수화 버전 호출**

Print(d, i); →  Print<double, int>; **부분 특수화 버전 호출**

STL