템플릿(Template)
→ (C++에서) 타입에 관계없이 알고리즘을 기술하는 프로그래밍 패러다임이라는 기능을 지원하는 것이다.
템플릿 문법
- 템플릿의 종류
- 클래스 템플릿 (Class Template)
- 함수 템플릿 (Function Template)
- 문법의 구성
template <parameter-list> declaration
- **
= template <매개 변수-열거> 선언**이라고 할 수 있다.
// 클래스 템플릿 정의하는 법
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 Parameter)
- 비 타입 파라미터(Non-type Parameter)
- 타입 파라미터(Type Parameter)
- 템플릿 파라미터(Template Parameter)
- 템플릿은 하나 이상의 템플릿 파라미터와 함께 매개변수화 된다.
- 타입(Type)도 인자처럼 전달할 수 있다.
**타입 파라미터가 타입을 받을 수 있다**
→
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! : 정의가 없다.
- 명시적 특수화(Explicit Specialization)
- 부분 특수화(Partial Specialization)
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