도순씨의 코딩일지
C++ :: 템플릿의 특수화, 인자, 매개변수, 디폴트값 본문
🌼 Point 클래스 템플릿과 배열 클래스 템플릿
다음과 같은 형태는 생소하지만 템플릿 클래스의 객체를 저장할 수 있습니다.
1
|
BoundCheckArray<Point<int>> oarr(50);
|
cs |
만약 저장대상이 Point<int> 템플릿 클래스 객체가 아닌 Point<int>형 포인터라면 다음과 같이 표현 가능합니다.
1
|
BoundCheckArray<Point<int>*> oparr(50);
|
cs |
예제를 통해서 직접 살펴봅시다.
⭐️ PointTemplate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#ifndef __POINT_TEMPLATE_H_
#define __POINT_TEMPLATE_H_
template <typename T>
class Point{
private:
T xpos, ypos;
public:
Point(T x = 0 , T y = 0);
void ShowPosition() const;
};
template <typename T>
Point<T> :: Point(T x, T y) : xpos(x), ypos(y) {}
template <typename T>
void Point<T>::ShowPosition() const {
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
#endif
|
cs |
⭐️ ArrayTemplate.h
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
|
#ifndef __ARRAY_TEMPLATE_H_
#define __ARRAY_TEMPLATE_H_
#include <iostream>
#include <cstdlib>
using namespace std;
template <typename T>
class BoundCheckArray{
private:
T* arr;
int arrlen;
BoundCheckArray(const BoundCheckArray& arr){}
BoundCheckArray& operator=(const BoundCheckArray& arr){}
public:
BoundCheckArray(int len);
T& operator[](int idx);
T operator[](int idx) const;
int GetArrLen() const;
~BoundCheckArray();
};
template <typename T>
BoundCheckArray<T> :: BoundCheckArray(int len) : arrlen(len) {
arr = new T[len];
}
template <typename T>
T& BoundCheckArray<T> :: operator[] (int idx){
if(idx < 0 || idx >= arrlen){
cout << "Array index out of bound exception" << endl;
exit(1);
}
return arr[idx];
}
template <typename T>
T BoundCheckArray<T> :: operator[] (int idx) const{
if(idx < 0 || idx >= arrlen){
cout << "Array index out of bound exception" << endl;
exit(1);
}
return arr[idx];
}
template <typename T>
int BoundCheckArray<T> :: GetArrLen() const {
return arrlen;
}
template <typename T>
BoundCheckArray<T> :: ~BoundCheckArray() {
delete []arr;
}
#endif
|
cs |
⭐️ BoundArrayMain.cpp
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
|
#include <iostream>
#include "ArrayTemplate.h"
#include "PointTemplate.h"
using namespace std;
int main(void){
BoundCheckArray<Point<int>> oarr1(3);
oarr1[0] = Point<int>(3, 4);
oarr1[1] = Point<int>(5, 6);
oarr1[2] = Point<int>(7, 8);
for(int i = 0 ; i < oarr1.GetArrLen() ; i++)
oarr1[i].ShowPosition();
BoundCheckArray<Point<double>> oarr2(3);
oarr2[0] = Point<double>(3.14, 4.31);
oarr2[1] = Point<double>(5.09, 6.07);
oarr2[2] = Point<double>(7.82, 8.54);
for(int i = 0 ; i < oarr2.GetArrLen() ; i++)
oarr2[i].ShowPosition();
typedef Point<int>* POINT_PTR;
BoundCheckArray<POINT_PTR> oparr(3);
oparr[0] = new Point<int>(11, 12);
oparr[1] = new Point<int>(13, 14);
oparr[2] = new Point<int>(15, 16);
for(int i = 0 ; i < oparr.GetArrLen() ; i++)
oparr[i] -> ShowPosition();
delete oparr[0]; delete oparr[1]; delete oparr[2];
return 0;
}
|
cs |
⭐️ 실행결과
1
2
3
4
5
6
7
8
9
|
[3, 4]
[5, 6]
[7, 8]
[3.14, 4.31]
[5.09, 6.07]
[7.82, 8.54]
[11, 12]
[13, 14]
[15, 16]
|
cs |
🌼 클래스 템플릿의 특수화
클래스 템플릿을 특수화하는 이유는 특정 자료형을 기반으로 생성된 객체에 대해, 구분이 되는 다른 행동양식을 적용하기 위해서입니다.
⭐️ ClassTemplateSpecialization.cpp
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
|
#include <iostream>
#include <cstring>
using namespace std;
template <typename T>
class Point{
private:
T xpos, ypos;
public:
Point(T x = 0, T y = 0) : xpos(x), ypos(y){}
void ShowPosition() const{
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
};
template <typename T>
class SimpleDataWrapper{
private:
T mdata;
public:
SimpleDataWrapper(T data) : mdata(data){}
void ShowDataInfo(void){
cout << "Data: " << mdata << endl;
}
};
template<>
class SimpleDataWrapper<char *>{
private:
char* mdata;
public:
SimpleDataWrapper(char* data){
mdata = new char[strlen(data) + 1];
strcpy(mdata, data);
}
void ShowDataInfo(void){
cout << "String: " << mdata << endl;
cout << "Length: " << strlen(mdata) << endl;
}
~SimpleDataWrapper() {delete []mdata;}
};
template <>
class SimpleDataWrapper<Point<int>>{
private:
Point<int> mdata;
public:
SimpleDataWrapper(int x, int y) : mdata(x, y){}
void ShowDataInfo(void){
mdata.ShowPosition();
}
};
int main(void){
SimpleDataWrapper<int> iwrap(170);
iwrap.ShowDataInfo();
SimpleDataWrapper<char*> swrap("Class Template Specialization");
swrap.ShowDataInfo();
SimpleDataWrapper<Point<int>> poswrap(3, 7);
poswrap.ShowDataInfo();
return 0;
}
|
cs |
⭐️ ClassTemplateSpecialization.cpp 실행결과
1
2
3
4
|
Data: 170
String: Class Template Specialization
Length: 29
[3, 7]
|
cs |
🌼 클래스 템플릿의 부분 특수화
아래와 같은 클래스가 있다고 가정해봅시다.
1
2
|
template <typename T1, typename T2>
class MySimple{....}
|
cs |
만약 T1과 T2를 각각 char과 int로 하여 특수화를 진행한다고 가정해봅시다. 다음과 같이 형태를 바꿀 수 있습니다.
1
2
|
template <>
class MySimple<char, int> {....}
|
cs |
예제를 통해 다시 확인해봅시다.
⭐️ ClassTemplatePartialSpecialization.cpp
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
|
#include <iostream>
using namespace std;
template <typename T1, typename T2>
class MySimple{
public:
void WhoAreyou(){
cout << "size of T1: " << sizeof(T1) << endl;
cout << "size of T2: " << sizeof(T2) << endl;
cout << "<typename T1, typename T2>" << endl;
}
};
template<>
class MySimple<int, double>{
public:
void WhoYouAre(){
cout << "size of int: " << sizeof(int) << endl;
cout << "size of double: " << sizeof(double) << endl;
cout << "<int, double>" << endl;
}
};
/*
template <typename T1>
class MySimple<T1, double>{
public:
void WhoAreayou(){
cout << "size of T1: " << sizeof(T1) << endl;
cout << "size of double" << sizeof(double) << endl;
cout << "<T1, double>" << endl;
}
};
*/
int main(void){
MySimple<char, double> obj1;
obj1.WhoAreyou();
MySimple<int, long> obj2;
obj2.WhoAreyou();
MySimple<int, double> obj3;
obj3.WhoYouAre();
return 0;
}
|
cs |
⭐️ ClassTemplatePartialSpecialization.cpp 실행결과
1
2
3
4
5
6
7
8
9
|
size of T1: 1
size of T2: 8
<typename T1, typename T2>
size of T1: 4
size of T2: 8
<typename T1, typename T2>
size of int: 4
size of double: 8
<int, double>
|
cs |
위 주석처리된 상태에서는 <int, double>에 대해서만 특수화 처리가 되어 있습니다. 주석을 해제하면 어떻게 될까요? <T1, double>에 대해서 부분 특수화가 진행됩니다.
⭐️ ClassTemplatePartialSpecialization.cpp 실행결과
1
2
3
4
5
6
7
8
9
|
size of T1: 1
size of double8
<T1, double>
size of T1: 4
size of T2: 8
<typename T1, typename T2>
size of int: 4
size of double: 8
<int, double>
|
cs |
🌼 템플릿 인자
결정되지 않은 자료형을 의미하는 용도로 사용되는 T와 같은 문자를 '템플릿 매개변수'라고 합니다. 그리고 템플릿 매개변수에 전달되는 자료형 정보를 '템플릿 인자'라고 합니다.
다음 예제를 살펴봅시다.
1
2
3
4
5
6
7
8
9
|
template <typename T, int len>
class SimpleArray{
private:
T arr[len];
public:
T& operator[] (int idx){
return arr[idx]
}
};
|
cs |
이렇게 템플릿 매개변수에도 변수가 올 수 있습니다. 예제를 한 번 봅시다.
⭐️ NonTypeTemplateParam.cpp
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
|
#include <iostream>
using namespace std;
template <typename T, int len>
class SimpleArray{
private:
T arr[len];
public:
T& operator[] (int idx) { return arr[idx];}
SimpleArray<T, len>& operator=(const SimpleArray<T, len>& ref){
for(int i = 0 ; i < len ; i++)
arr[i] = ref.arr[i];
return *this;
}
};
int main(void){
SimpleArray<int, 5> i5arr1;
for(int i = 0 ; i < 5 ; i++)
i5arr1[i] = i * 10;
SimpleArray<int, 5> i5arr2;
i5arr2 = i5arr1;
for(int i = 0 ; i < 5 ; i++)
cout << i5arr2[i] << ", ";
cout << endl;
SimpleArray<int, 7> i7arr1;
for(int i = 0 ; i < 7 ; i++)
i7arr1[i] = i * 10;
SimpleArray<int, 7> i7arr2;
i7arr2 = i7arr1;
for(int i = 0 ; i < 7 ; i++)
cout << i7arr2[i] << ", ";
cout << endl;
return 0;
}
|
cs |
⭐️ NonTypeTemplateParam.cpp 실행결과
1
2
|
0, 10, 20, 30, 40,
0, 10, 20, 30, 40, 50, 60,
|
cs |
길이가 같은 두 배열 객체간의 대입만이 허용됩니다. 이렇듯 템플릿 매개변수에 값을 저장받을 수 있는 변수를 선언하면, 변수에 전달되는 상수를 통해서 서로 다른 형의 클래스가 생성되게 할 수 있습니다.
🌼 템플릿 매개변수와 디폴트 값
템플릿 매개변수에도 디폴트 값 지정이 가능합니다. 다음 예제를 살펴봅시다.
⭐️ TemplateParamDefaultValue.cpp
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 | #include <iostream> using namespace std; template <typename T = int, int len = 7> // 디폴트 값 지정 class SimpleArray{ private: T arr[len]; public: T& operator[] (int idx){ return arr[idx];} SimpleArray<T, len>& operator= (const SimpleArray<T, len> &ref){ for(int i = 0 ; i < len ; i++) arr[i] = ref.arr[i]; return *this; } }; int main(void){ SimpleArray<> arr; for(int i = 0 ; i < 7 ; i++) arr[i] = i + 1; for(int i = 0 ; i < 7 ; i++) cout << arr[i] << " "; cout << endl; return 0; } | cs |
⭐️ TemplateParamDefaultValue.cpp 실행결과
1 | 1 2 3 4 5 6 7 | cs |
'𝐏𝐑𝐎𝐆𝐑𝐀𝐌𝐌𝐈𝐍𝐆 > 𝐂++' 카테고리의 다른 글
C++ :: STL이란? (0) | 2020.09.08 |
---|---|
C++ :: 예외처리(try, catch, throw) (0) | 2020.09.02 |
C++ :: 템플릿(Template), 클래스 템플릿(class Template) (0) | 2020.08.31 |
C++ :: 디폴트 대입 연산자, 배열의 인덱스 연산자 오버로딩, const 함수 오버로딩 (0) | 2020.08.30 |
C++ :: 연산자 오버라이딩, 단항 연산자의 오버로딩, 전위증가와 후위증가 오버로딩 (0) | 2020.08.29 |