C++ Template
C++ Template에 대해 정리한다.
ㆍ기능적 측면은 정해져 있으나, 데이터 타입은 정해져 있지 않을 경우 또는 다양한 데이터 타입을 하나의 기능으로 처리하도록 하기 위해 사용함
표준 템플릿의 모음 : STL(Standard Template Library)
형태
1
2
template <typename T>
// == template <class T>
T라는 이름(typename)에 대해, 다음에 정의하는 대상을 템플릿으로 선언한다
함수템플릿
ㆍ다중 인자(둘 이상의 타입) 템플릿
ㆍ함수템플릿 특수화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
template <typename T> // 타입에 상관없이 덧셈 연산 수행
T Add(T a, T b){
return a+b;
}
template <typename T1, typename T2> // 둘 이상의 타입에 대응
void ShowData(T1 a, T2 b){
cout << "[ " << a << ", " << b << " ]" << endl;
}
template <typename T>
int SizeOf(T a){
return sizeof(a);
}
// 정확한 표현
// template <> int SizeOf<char *>(char* a)
template <> // 함수 템플릿 특수화 선언
int SizeOf(const char * a){ // 전달 인자가 char*인 경우에는 이 함수 호출
return strlen(a);
}
int main(void){
int i=10;
const char* str = "Hello!";
cout << "--------------------------" << endl;
// 인자에 상관없는 덧셈 연산
cout << Add(10, 20) << endl;
cout << Add(1.1, 2.2) << endl;
cout << "--------------------------" << endl;
// 서로 다른 두개의 타입에 대한 처리
ShowData(1, 2);
ShowData(3, 2.5);
cout << "--------------------------" << endl;
// 특수한 타입에 대하여 별도 연산(함수 템플릿 특수화)
cout << SizeOf(i) << endl;
cout << SizeOf(str) << endl;
return 0;
}
클래스템플릿
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
using std::cout;
using std::endl;
template <typename T>
class Data{
private:
T data;
public:
Data(T d);
void SetData(T d);
T Getdata();
};
template <typename T>
Data<T>::Data(T d){ // Data<T> 형태로 선언해 주어야함
data=d;
}
template <typename T>
void Data<T>::SetData(T d){
data=d;
}
template <typename T>
T Data<T>::Getdata(){
return data;
}
int main(void){
Data<int> d1(0); // T를 int로 간주하고 객체를 생성함
d1.SetData(100);
Data<char> d2('c'); // T를 char로 간주하고 객체를 생성함
cout << d1.Getdata() << endl;
cout << d2.Getdata() << endl;
return 0;
}
1
2
3
4
// 객체 생성
// ClassName<typename> Object<type>
Data<int> d1(0);
Data<char> d2('C');
클래스 템플릿을 기반으로 객체 생성 시,결정하고자 하는 자료형을 명시적으로 선언
ㆍ객체 생성 순서는 메모리 할당 → 생성자 호출
ㆍ생성자 호출 시, 전달 인자를 통해 자료형을 결정하고자 할 경우, 메모리 할당에 문제가 생김
ㆍ따라서, 메모리 공간 할당을 위한 명시적 선언 필요
ㆍ다른 이유는(근본적), 클래스 템플릿은 생성자를 통해서 전달되는 인자의 자료형과 결정되어야 할 템플릿의 자료형이 다를 수 있음
1
2
3
// ClassName<typename>::FunctionName(type...)
Data<T>::SetData(); // a
Data::SetData(); // b
클래스 템플릿의 선언과 정의를 구분할 경우, ‘a’ 형식을 사용
ㆍa : T 타입에 대해서 템플릿으로 정의되어 있는 Data 클래스 템플릿의 멤버함수 정의
ㆍb : Data 클래스의 멤버함수 정의
Stack 템플릿화
다양한 데이터를 저장하기 위한 Stack 객체를 생성 가능하게 함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
// =============== 아래 프로그램을 Template화 =================
#include <iostream>
using std::cout;
using std::endl;
class Stack{
private:
int topIdx; // 마지막 입력된 위치의 인덱스
char* stackPtr; // 스택포인터
public:
Stack(int s=10);
~Stack();
void Push(const char& pushValue);
char Pop();
};
Stack::Stack(int len){
topIdx=-1; // 스택 인덱스 초기화
stackPtr=new char[len]; // 데이터 저장 위한 배열 선언
}
Stack::~Stack(){
delete [] stackPtr;
}
void Stack::Push(const char& pushValue){ // 스택에 데이터 입력
stackPtr[++topIdx] = pushValue;
}
char Stack::Pop(){ // 스택에서 데이터 꺼냄
return stackPtr[topIdx--];
}
int main(){
Stack stack(10);
stack.Push('A');
stack.Push('B');
stack.Push('C');
for(int i=0; i<3; i++){
cout << stack.Pop() << endl;
}
return 0;
}
*/
#include <iostream>
using std::cout;
using std::endl;
template <typename T>
class Stack{
private:
int topIdx; // 마지막 입력된 위치의 인덱스
T* stackPtr; // 스택포인터
public:
Stack(int s=10);
~Stack();
void Push(const T& pushValue);
T Pop();
};
template <typename T>
Stack<T>::Stack(int len){
topIdx=-1; // 스택 인덱스 초기화
stackPtr=new T[len]; // 데이터 저장 위한 배열 선언
}
template <typename T>
Stack<T>::~Stack(){
delete [] stackPtr;
}
template <typename T>
void Stack<T>::Push(const T& pushValue){ // 스택에 데이터 입력
stackPtr[++topIdx] = pushValue;
}
template <typename T>
T Stack<T>::Pop(){ // 스택에서 데이터 꺼냄
return stackPtr[topIdx--];
}
int main(){
Stack<char> stack1(10);
stack1.Push('A');
stack1.Push('B');
stack1.Push('C');
for(int i=0; i<3; i++){
cout << stack1.Pop() << endl;
}
Stack<int> stack2(10);
stack2.Push(100);
stack2.Push(200);
stack2.Push(300);
for(int i=0; i<3; i++){
cout << stack2.Pop() << endl;
}
return 0;
}
템플릿 인스턴스화
함수 템플릿은 타입별로 실제 호출이 가능하게 만들어지는 템플릿 함수를 만들기 위한 틀
클래스 템플릿은 객체화가 가능한 클래스를 만들기 위한 틀
클래스 템플릿은 하나의 파일 내에 선언과 정의가 함께 있어야 함(2011년, 이 후 확인 필요)