함수와 클래스가 특정 자료형을 사용하지 않고 여러 자료형을 가질 수 있도록 함.
(제네릭 프로그래밍 (Generic Programming))
여러 자료형의 함수를 만들어내기 위한 템플릿.
어떤 자료형이 들어올지 모르기 때문에, 모든 자료형에 대해 함수 오버로딩 필요.
#include <iostream>
using namespace std;
void Print(int a, int b)
{
cout << a << ',' << b << endl;
}
void Print(double a, double b)
{
cout << a << ',' << b << endl;
}
void Print(const char* a, const char* b)
{
cout << a << ',' << b << endl;
}
int main()
{
Print(1, 2);
Print(1.1, 2.2);
Print("Taeil", "Nam");
return 0;
}
template 키워드 사용.
typename으로 만들어준 'T' 자료형을 사용하면, 'T' 자료형이 특정 자료형으로 변경된 새로운 함수가 만들어짐.
#include <iostream>
using namespace std;
template<typename T> // 템플릿으로 T라는 typename 지정.
void Print(T a, T b) // 두 매개 변수의 자료형을 T로 지정.
{
cout << a << ',' << b << endl;
}
int main()
{
Print(1, 2); // Print(int a, int b) 를 호출한 것과 같음.
Print(1.1, 2.2); // Print(double a, double b) 를 호출한 것과 같음.
Print("Taeil", "Nam"); // Print(const char* a, const char* b) 를 호출한 것과 같음.
return 0;
}
호출자가 직접 자료형을 명시적으로 지정하여 함수 호출.
동작은 함수 템플릿 사용과 동일.
#include <iostream>
using namespace std;
template<typename T> // 템플릿으로 T라는 typename 지정.
void Print(T a, T b) // 두 매개 변수의 타입을 T로 지정.
{
cout << a << ',' << b << endl;
}
int main()
{
Print<int>(1, 2); // Print(int a, int b) 를 명시적 호출.
Print<double>(1.1, 2.2); // Print(double a, double b) 를 명시적 호출.
Print<const char*>("Taeil", "Nam"); // Print(const char* a, const char* b) 를 명시적 호출.
return 0;
}
템플릿도 함수처럼 여러 개의 매개 변수 사용 가능.
#include <iostream>
using namespace std;
template<typename T1, typename T2> // 템플릿 매개 변수 T1, T2 지정.
void Print(T1 a, T2 b) // 두 매개 변수의 자료형을 각각 T1, T2로 지정.
{
cout << a << ',' << b << endl;
}
int main()
{
Print(1, "Taeil"); // Print(int a, const char* b) 를 호출.
return 0;
}
템플릿으로 만든 함수를 모든 자료형이 사용할 수 있는 건 아님.
함수에 정의되어 있는 연산이 가능한 자료형이어야 함.
특정 자료형만 따로 처리하려면, 함수 템플릿 특수화 사용.
class Point
{
public:
Point(int x, int y) : _x(x), _y(y) { }
void Print() { cout << _x << ',' << _y << endl; }
private:
int _x = 0;
int _y = 0;
};
template<typename T>
void Print(T a)
{
cout << a << endl; // Point 객체는 '<<' 연산자 오버로딩이 없으므로 사용불가.
}
#include <iostream>
using namespace std;
class Point
{
public:
Point(int x, int y) : _x(x), _y(y) { }
void Print() { cout << _x << ',' << _y << endl; }
private:
int _x = 0;
int _y = 0;
};
template<typename T>
void Print(T a)
{
cout << a << endl;
}
template<> // 함수 템플릿 특수화
void Print(Point a)
{
a.Print();
}
int main()
{
int a = 1;
double b = 3.14;
const char* c = "nam";
Point p(5, 5);
Print(a);
Print(b);
Print(c);
Print(p);
return 0;
}
함수 템플릿과 동일하다.. 함수->클래스로 바꿔서 생각 하면 됨.
클래스 템플릿을 사용해서 아주 간단하게 큐를 흉내내보는 예제.
#include <iostream>
using namespace std;
template<typename T> // 클래스 템플릿
class Queue
{
public:
void Push(T data)
{
_buffer[_i++] = data;
}
T Pop()
{
T result = _buffer[_pop];
_buffer[_pop++] = 0;
return result;
}
bool Empty()
{
return (_pop == 10);
}
private:
T _buffer[10];
size_t _i = 0;
size_t _pop = 0;
};
int main()
{
Queue<int> q;
q.Push(10);
q.Push(20);
q.Push(30);
if (!q.Empty())
cout << q.Pop() << endl;
if (!q.Empty())
cout << q.Pop() << endl;
if (!q.Empty())
cout << q.Pop() << endl;
return 0;
}