일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- programmers
- logistic regression
- Python
- pwnable.kr
- tensorflow
- Algorithm
- 기능개발
- AI
- Linear_regression
- Softmax classification
- 텐서플로
- 인공지능
- leg
- Today
- Total
나혼자 공부장
[윤성우] Chap13. 템플릿(template) 본문
템플릿에 대한 이해와 함수 템플릿
함수 템플릿 : 함수를 만드는 도구
함수 템플릿은 다양한 자료형의 함수를 만들어낼 수 있다.
함수의 기능은 정해져있고, 용도에 따라 달라지는 자료형을 결정하기 위한 템플릿이라고 이해하면 된다.
아래와 같이 정의한다.
template <typename T> //template <class T> 와 같은 의미
T add(T num1, T num2){
return num1+num2;
}
예제 1.
/* 덧셈 템플릿 구현 및 사용 */
#include <iostream>
using namespace std;
template <typename T>
T Add (T num1, T num2){
return num1+num2;
}
int main(void) {
cout << Add<int>(15, 20) <<endl;
cout << Add<double>(2.9, 3.7) <<endl;
cout << Add<int>(3.2, 3.2) <<endl; // int 함수에 double형 실수 전달로 값 손실 발생
cout << Add<int>(3.14, 2.75) <<endl;
return 0;
}
위 예제의 경우 컴파일러에서 템플릿을 사용할 때마다 함수가 하나 만들어준다.
위는 int, double 두 가지 자료형이 쓰였으므로 총 두 가지의 함수가 만들어진다.
물론 그만큼 속도의 감소가 발생하지만 실행속도가 아닌 컴파일 시의 속도이므로 크게 신경 쓸 요소는 아니다.
Add(15, 20) 처럼 일반 함수 호출처럼 호출해도 된다.
이럴 때는 컴파일러에서 파라미터 자료형에 맞춰 알아서 자료형을 결정한다.
예제를 일반 함수 호출처럼 하면 파라미터와 자료형에 무조건 따르기 때문에 이전 실행 결과와 같은 값 손실이 발생하지 않는다.
1. 함수 템플릿과 템플릿 함수
함수 템플릿 : 함수를 만드는데 사용되는 템플릿
템플릿 함수 : 템플릿을 기반으로 만들어진 함수
둘 이상의 타입에 대해서도 템플릿 선언이 가능하다.
예제 2.
/* 둘 이상의 템플릿 구현 및 사용 */
#include <iostream>
using namespace std;
template <class T1, class T2>
void ShowData(double num) {
cout << static_cast<T1> (num) << ", " << static_cast<T2> (num) << endl;
}
int main(void) {
ShowData<char, int>(65);
ShowData<char, int>(67);
ShowData<char, int>(68.9);
ShowData<char, int>(69.2);
ShowData<char, int>(70.4);
return 0;
}
2. 함수 템플릿의 특수화
같은 함수 템플릿이라도 용도가 뭐냐에 따라 세부 기능을 조금씩 달리해야 할 때가 있다.
ex) 크기 비교 시 문자열의 경우 사전편찬 순 비교인지, 단순 문자열의 길이 비교인지 등
예제 3.
/* 함수의 특수화 */
#include <iostream>
#include <cstring>
using namespace std;
template <class T>
T Max(T a, T b) {
return a > b ? a : b;
}
template <>
char* Max(char *a, char *b) { // 문자열 길이 비교
cout << "char* Max <char *>(char *a, char *b)" << endl;
return strlen(a) > strlen(b) ? a : b;
}
template <>
const char* Max(const char* a, const char* b) { // 문자열 사전편찬 순 비교
cout << "const char* Max <const char *>(const char *a, const char *b)" << endl;
return strcmp(a, b) > 0 ? a : b;
}
int main(void) {
cout << Max(11, 15) << endl;
cout << Max('T', 'Q') << endl;
cout << Max(3.5, 7.5) << endl;
cout << Max("Simple", "Best") << endl;
char str1[] = "Simple";
char str2[] = "Best";
cout << Max(str1, str2) << endl;
return 0;
}
클래스 템플릿
1. 클래스 템플릿의 정의
함수를 템플릿으로 정의한게 함수 템플릿이였던 것처럼, 클래스를 템플릿으로 정의한게 클래스 템플릿
정의하고 사용하는 개념은 함수 템플릿의 경우와 동일하다.
클래스 템플릿 기반의 객체생성에는 자료형 정보 생략이 불가능하다.
예제 4.
/* 클래스 템플릿 */
#include <iostream>
using namespace std;
template <class 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;
}
};
int main(void) {
Point<int> pos1(3, 4);
pos1.ShowPosition();
Point<double> pos2(2.4, 3.6);
pos2.ShowPosition();
Point<char> pos3('P', 'F');
pos3.ShowPosition();
return 0;
}
2. 클래스 템플릿의 선언과 정의의 분리
클래스 템플릿 또한 멤버함수를 클래스 외부에 정의하는 것이 가능하다.
클래스 템플릿의 정의와 함수의 정의는 완전히 별개이기에, 각각에 대해서 문자 T가 무엇을 의미하는지 정의해야 한다.
예제 5.
/* 예제 4에서 멤버함수를 외부에 정의한 버전 */
#include <iostream>
using namespace std;
template <class T>
class Point {
private:
T xpos, ypos;
public:
Point(T x = 0, T y = 0);
void ShowPosition() const;
};
template <class T>
Point<T>::Point(T x, T y) : xpos(x), ypos(y){}
template <class T>
void Point<T>::ShowPosition() const {
cout << '[' << xpos << ", " << ypos << ']' << endl;
}
int main(void) {
Point<int> pos1(3, 4);
pos1.ShowPosition();
Point<double> pos2(2.4, 3.6);
pos2.ShowPosition();
Point<char> pos3('P', 'F');
pos3.ShowPosition();
return 0;
}
3. 배열 클래스의 템플릿화
예제 6. 각 자료형마다 배열 만들기
/*** ArrayTemplate.h ***/
#ifndef __ARRAY_TEMPLATE_H_
#define __ARRAY_TEMPLATE_H_
#include <iostream>
#include <cstdlib>
using namespace std;
template <class 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 <class T>
BoundCheckArray<T>::BoundCheckArray(int len) : arrlen(len) {
arr = new T[len];
}
template <class 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 <class 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 <class T>
int BoundCheckArray<T>::GetArrLen() const {
return arrlen;
}
template <class T>
BoundCheckArray<T>::~BoundCheckArray() {
delete[] arr;
}
#endif
/*** Point.h ***/
#ifndef __POINT_H_
#define __POINT_H_
#include <iostream>
using namespace std;
class Point {
private:
int xpos, ypos;
public:
Point(int x = 0, int y = 0);
friend ostream& operator<<(ostream& os, const Point& pos);
};
#endif
/*** BoundArrayMain.cpp ***/
#include <iostream>
#include "ArrayTemplate.h"
#include "Point.h"
using namespace std;
int main(void) {
/*** int형 정수 저장 ***/
BoundCheckArray<int> iarr(5);
for (int i = 0; i < 5; i++)
iarr[i] = (i + 1) * 11;
for (int i = 0; i < 5; i++)
cout << iarr[i] << endl;
/*** Point 객체 저장 ***/
BoundCheckArray<Point> oarr(3);
oarr[0] = Point(3, 4);
oarr[1] = Point(5, 6);
oarr[2] = Point(7, 8);
for (int i = 0; i < oarr.GetArrLen(); i++)
cout << oarr[i];
/*** Point 객체의 주소 값 저장 ***/
typedef Point* POINT_PTR;
BoundCheckArray<POINT_PTR> parr(3);
parr[0] = new Point(3, 4);
parr[1] = new Point(5, 6);
parr[2] = new Point(7, 8);
for (int i = 0; i < parr.GetArrLen(); i++)
cout << *(parr[i]);
delete parr[0];
delete parr[1];
delete parr[2];
return 0;
}
/*** Point.cpp ***/
#include <iostream>
#include "Point.h"
using namespace std;
Point::Point(int x, int y) : xpos(x), ypos(y) {}
ostream& operator<<(ostream& os, const Point& pos) {
os << '[' << pos.xpos << ", " << pos.ypos << ']' << endl;
return os;
}
'C++ > 윤성우' 카테고리의 다른 글
[윤성우] Chap 14. 템플릿(template) 2 (0) | 2020.02.07 |
---|---|
[윤성우] Chap 13. 템플릿 tasks write-up (0) | 2020.02.07 |