[C++] 템플릿(template)
REF : 윤성우의 열혈 C++
함수템플릿
- 함수템플릿은 다양한 자료형의 함수를 만들어낼 수 있다.
-
int Add(int num1, int num2) { return (num1 + num2); }
위와같은 함수는
-
template <typename T> T add(T num1, T num2) { return (num1 + num2); }
이렇게 함수템플릿으로 선언할 수 있다.
-
-
template <typename T>
대신,template <class T>
로도 선언할 수 있다. - 실제로 위 함수가 사용되는 예시는 아래와 같다.
int main(void) { cout<<Add<int>(15, 20) <<endl; cout<<Add<double>(2.9, 3.7) <<endl; cout<<Add<int>(3, 3) <<endl; cout<<Add<double>(3.14, 2.75) <<endl; return (0); }
- 함수 호출 시, 함수와 매개변수 사이에
<변환될 자료형>
을 넣어줄수도 있다. - 넣지않는다면, 컴파일러가 자료형으로 알아서 변환한다.
- 컴파일러가 자료형으로 만드는 함수를
템플릿 함수
라고한다. - 또는,
생성된 함수
라고도 불린다.
둘 이상의 형에 대해 템플릿 선언
- 템플릿의 정의에 다양한 자료형도 선언할 수 있다.
- 둘 이상의 형에 대해서 템플릿을 선언할 수 있다.
template <class T1, class T2>
void ShowData(double num)
{
cout<<(T1)num<<", "<<(T2)num<<endl;
}
int main(void)
{
ShowData<char, int>(65);
ShowData<char, int>(67);
ShowData<char, double>(68.9);
ShowData<short, double>(69.2);
ShowData<short, double>(70.4);
return 0;
}
함수 템플릿의 특수화
- 템플릿 함수를 상황에따라 다르게 구성해야할수도 있다.
- 단순히 크기 비교가 아닌, 문자열의 길이를 비교한다던지,
- 사전편찬 순으로 비교한다던지를 하기위해서는
함수 템플릿 특수화
를 해야한다.
template<>
char *Max<char *>(char *a, char *b)
{
return (strlen(a) > strlen(b) ? a : b)
}
template<>
const char *Max<const char *>(const char *a, const char *b)
{
return (strcmp(a, b)> 0 ? a : b);
}
- 컴파일러에게 특수화할 자료형의 함수를 전달해 해당 자료형의 경우에는 정의한 함수를 사용하도록한다.
클래스 템플릿
- 함수를 템플릿으로 정의했듯, 클래스도 템플릿으로 정의할 수 있다.
- 이렇게 정의된 템플릿을
클래스 템플릿
, 이를 바탕으로 만들어진 클래스를템플릿 클래스
라고한다.
클래스 템플릿의 정의
- 저장하는 멤버변수가 다르다는 이유만으로 유사한 클래스를 여러개 정의하는 것은 비효율적이다.
-
이때 사용되는게 클래스 템플릿이다.
- 정수형 좌표를 저장하는 클래스 예시
class Point { private : int x; int y; public: Point(int x, int y) : x(x), y(y) {} void ShowPosition() const { ... } };
내부 멤버변수가 float, char * 등등인 경우에 클래스를 각각 생성하는건 비효율적이다.
이때, 클래스 템플릿을 사용한다.
template <typename T>
class Point
{
private:
T x;
T y;
public:
Point(T x, T y) : x(x), y(y)
void ShowPosition() const
{
...
}
};
- 컴파일러는 클래스 템플릿을 기반으로 템플릿 클래스를 만들어낸다.
- 필요한 템플릿 클래스를 만들어서 객체를 생성해낸다.
단, 클래스 템플릿은 반드시 객체생성시 자료형을 명시해야한다.
클래스 템플릿의 몸체 분리
- 위의 Point 클래스 템플릿의 몸체를 분리해보자.
template <typename T>
class Point
{
private:
T x;
T y;
public:
Point(T x, T y);
void ShowPosition() const;
};
template <typename T>
Point<T>::Point(T x, T y) : x(x), y(y)
{}
template <typename T>
void Point<T>::ShowPosition() const
{
...
}
- 함수의 몸체에도 template을 선언해주어야 컴파일러가 잘 인식한다.
클래스 템플릿으로 템플릿 클래스의 객체를 담는 객체 생성
- 클래스 템플릿을 정의하면 어느 자료형이든 받을 수 있다.
- 이에는 다른 클래스 템플릿으로 정의되어 생성된 템플릿 클래스도 담길 수 있다.
BoundCheckArray<int> iarr[50]; //int형 자료형을 담을 수 있다.
BoundCheckArray<Point<int>> parr[50]; //Point<int> 템플릿 클래스의 객체도 담을 수 있다.
BoundCheckArray<Point<int>*> ㅐparr[50]; //Point<int> 템플릿 클래스의 객체의 포인터도 담을 수 있다.
클래스 템플릿의 특수화
- 함수템플릿을 특수화했듯, 클래스 템플릿도 특수화할 수 있다.
자료형에따라 다른 행동양식을 정하기 위해서
사용한다.
template <typename T>
class A
{};
이런 클래스 템플릿에 대한 int 자료형에 대한 특수화는
template <>
class A<int>
{};
이렇게 할 수 있고, 객체를 생성하기 위해선
A<int> obj1;
으로 선언할 수 있다.
템플릿클래스 객체선언
-
클래스 템플릿을 기반으로한 템플릿 클래스의 객체 선언방법
- 저장대상이
tc<int>
일 경우A<tc<int>> obj;
- 저장대상이
tc<int>*
일 경우A<tc<int> *> obj;
- 저장대상이
댓글남기기