본문 바로가기

Archived(CSE Programming)/cpp

Chap 13. 템플릿(Template) 1

Chap 13. 템플릿(Template) 1


13-1. 템플릿에 대한 이해와 함수


1
2
int add(intint);
double add(doubledouble);
cs


템플릿은 말 그대로, 틀을 의미한다. 우리가 더하기를 수행하는 함수를 만들 때, 자료형이 다른 경우 오버로딩으로 해결하려하여도 반환형 까지 다르면 완전히 다른 함수를 만들어야 한다. 이 때, 우리는 자료형에 독립적인 함수를 만들 수 있는데 (정확히는 함수의 틀을 만들 수 있다) 그것이 바로 템플릿이다.


1
2
3
4
template <typename T>
T add(T num1, T num2){
    return num1+num2;
}
cs


다음과 같이, template을 선언해주고 자료형 매개변수로 T가 어떤 의미인지 명시해준다. 그리고 원하는 자료형 부분을 T로 치환해주면 우리가 원하는 함수 템플릿을 만들어줄 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
 
template <typename T>
T add(T num1, T num2){
    return num1+num2;
}
 
void main(){    
    cout<<add<int>(3,4)<<endl;
    cout<<add<double>(2.45.7)<endl;
    cout<<add(2,5)<<endl;
    cout<<add('a','b')<<endl;
}
cs


실 사용은 다음과 같이 이루어지는데 이 때, 컴파일러가 컴파일 때 미리 보고 우리가 원하는 형의 자료형 만큼 함수를 만들어 둔다. 그리고 12~13 라인 처럼 자료형을 명시해주지않아도 컴파일러가 판단이 가능할 경우에는 다음과 같이 사용이 가능하다(그러나 되지 않을 때도 있으니 주의하고 사용하도록 하여야 한다).


이러한 템플릿으로 함수 틀을 만들어 둔 것을 보고 함수 템플릿이라 하고 컴파일러가 이를 보고 만드는 함수를 템플릿 함수라고 한다. 또한 특별한 자료형의 경우에 대해서는 우리가 미리 선언해 둘 수 있는데 이를 함수 템플릿의 특수화라고 한다.


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
#include <iostream>
#include <cstring>
using namespace std;
 
template <typename T>
T add(T num1, T num2){
    return num1+num2;
}
 
template <>
const char* add<const char *>(const char* str1, const char* str2){
    char tempstr[100];
    strcpy(tempstr,str1);
    strcat(tempstr,str2);
    
    return tempstr;
}
 
void main(){    
    cout<<add<int>(3,4)<<endl;
    cout<<add<double>(2.45.7)<endl;
    cout<<add(2,5)<<endl;
    cout<<add('a','b')<<endl;
 
    cout<<add<const char*>("asd""bsd")<<endl;
}
cs



13-2. 클래스 템플릿


함수와 마찬가지로 클래스에 대해서도 템플릿을 선언하여 사용할 수 있다.

함수 템플릿과 마찬가지로 사용방법은 동일하지만 클래스 템플릿은 함수 템플릿과 달리 객체 생성자를 호출 시에 반드시 명시를 해주어야 한다. 왜냐하면 생성자와 별개로 자료형이 다를 수 있기에 컴파일러가 쉽게 판단할 수 없기 때문이다. 그래서 우리가 자료형을 명시해주어야 한다.


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
#include <iostream>
using namespace std;
 
template <typename T>
class BoundCheckArray{
private:
    T * arr;
    int len;
public:
    // 생성자
    BoundCheckArray(int l) :len(l){
        arr = new T[len];
    }
    // 복사 생성자
    BoundCheckArray(const BoundCheckArray & arr){}
    
    // = 연산자    
    BoundCheckArray& operator=(const BoundCheckArray & arr){}
    
    // [] 연산자
    T& operator[](int idx){
        if (idx <0 || idx >= len)
            exit(1);
        return arr[idx];
    }
    // [] 연산자 const 오버로딩
    T operator[](int idx) const{
        if (idx <0 || idx >= len)
            exit(1);
        return arr[idx];
    }
    
    // 소멸자
    ~BoundCheckArray(){
        delete[] arr;
    }
};
 
// 메인 함수
void main(){
    BoundCheckArray<int> intArr(5);
    BoundCheckArray<double> doubleArr(2);
 
    intArr[4= 3;
    doubleArr[1= 2.5;
    
    cout<<intArr[4]<<endl;
    cout<<doubleArr[1]<<endl;
}
 
cs


추가로, 템플릿은 헤더파일과 소스파일을 나눠놨을 때, 헤더파일만 메인 소스파일에 include 할 경우 에러가 난다. 컴파일러가 main 함수를 보고 컴파일 할시에 정의 부가 있어야 컴파일러가 함수든 클래스든 그에 맞게 만들어 둘 수 있기에 정의 부분이 있어야한다. 따라서 헤더파일에 정의 부분을 포함시키거나, 소스파일(cpp)도 메인 소스파일에 include 해주어야 한다.