본문 바로가기
CS/Study

[C++] 템플릿(Template)

by bona.com 2023. 5. 27.

함수 템플릿

int Add(int num1, int num2){
	return num1+num2;
}

위 함수의 기능과 자료형은 다음과 같다.

함수의 기능 덧셈
대상 자료형 int형 데이터

 

이러한 함수를 만들어 낼 수 있는 템플릿(모형자)는 다음과 같이 정의한다.

template <typename T>
T Add(T num1, T num2){
	return num1+num2;
}

이를 앞서 정의한 Add함수와 비교해 보면, int형 선언을 T로 대신했음을 알 수 있는데, 이는 자료형을 결정짓지 않은, 그래서 나중에 T를 대신해서 실제 자료형을 결정하겠다는 뜻이다.

함수의 기능 덧셈
대상 자료형 결정되어 있지 않음

위 코드에서 첫 번째 문장은 T라는 이름을 이용해서 아래의 함수를 템플릿으로 정의한다는 의미이다.

 

그럼 템플릿을 활용한 코드 하나를 만들어보겠다.

#include <iostream>
using namespace std;
template <typename T>
T Add(int num1, int num2){
	return num1+num2;
}
int main(void)
{
	cout << Add<int>(15, 20) << endl;
	cout << Add<double>(2.9, 3.7) << endl;
    return 0;
}

여기서 <int>가 의미하는 바는 "T를 int로 해서 만들어진 Add 함수를 호출한다"이다.

 

그리고 컴파일러에 의해 만들어지는 템플릿 함수는 일반함수와 구분된다.

 

템플릿 특수화

'템플릿 특수화(Speciallization of function template)'는 템플릿 구성방법에 예외를 둘 때 사용된다. 

템플릿 특수화를 사용한 코드는 다음과 같다.

#include <iostream>
#include <cstring>
using namespace std;

template <typename 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;
}

char* Max(char* a, char* b)에서는 컴파일러에게 char* 형 함수가 필요한 경우에는 별도로 만들지 말고 이 함수를 쓰라고 말해주고 있다.

 

클래스 템플릿

'클래스 템플릿(Class Template)'은 클래스로 템플릿을 정의하는 것이다.

다음의 코드로 살펴보자.

#include <iostream>
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;
	}
};
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개의 템플릿 클래스가 만들어진 것이다.

  • Point<int> 템플릿 클래스
  • Point<double> 템플릿 클래스
  • Point<char> 템플릿 클래스

 

템플릿 클래스는 템플릿 함수와는 달리 자료형 정보를 생략할 수 없다. 클래스 템플릿 기반의 객체생성에는 반드시 자료형 정보를 명시하도록 되어있다.

 

클래스 템플릿의 선언과 정의의 분리

클래스 템플릿도 멤버함수를 클래스 외부에 정의하는 것이 가능하다.

예를들어 다음과 같이 정의된 클래스 템플릿이 있다면

template <typename T>
class SimpleTemplate{
public:
	T SimpleFunc(const T& ref);
};

이 템플릿의 멤버함수 SimpleFunc는 다음과 같이 외부에 정의해야 한다.

template <typename T>
T SimpleTemplate<T>::SimpleFunc(const T& ref){

}

여기서 SimpleTemplate<T>가 의미하는 바는 T에 대해 템플릿화 된 SimpleTemplate 클래스 템플릿이다.