[C++] Chapter 13 - 템플릿(Template) 1

Lee Jeong Min·2021년 1월 18일
0

Cpp

목록 보기
13/16
post-thumbnail

13-1 템플릿(Template)에 대한 이해와 함수 템플릿

함수를 대상으로 템플릿 이해하기

함수 템플릿이란 함수를 만드는 도구가 되며 함수 템플릿을 통해 다양한 자료형의 함수를 만들어 낼수 있다.

예시

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

이러한 함수에선 함수의 기능이 덧셈이며 대상 자료형이 int형 데이터임을 알 수 있다.
위의 기능과 동일한 템플릿 함수는 다음과 같이 정의한다.

template <typename T> // typename 대신 class 도 가능, T도 다른 문자 가능
T Add(T num1, T num2)
{
    return num1+num2;
}

함수템플릿 예제

AddFunctionTemplate.cpp

#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;
	cout << Add<double>(3.14, 2.17) << endl;
	return 0;
}

위와 같이 함수 템플릿을 사용할 수 있으며 Add int(3.2, 3.2)의 경우 int형으로 소수점 자리가 손실되어 결과가 나온다. 또한 템플릿 함수를 호출 할때 굳이 <자료형>을 적어주지 않아도 컴팡일러가 전달되는 인자의 자료형을 판단하기 때문에 Add(3.2, 3.2)로 바로 적어주어 double형 연산을 한다.

둘 이상의 형에 대해 템플릿 선언하기

PrimitiveFunctionTemplate.cpp

#include <iostream>
using namespace std;

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

typename대신 위에서 템플릿을 정의할때 class를 사용을 해주었으며 함수에서 매개변수 형이 double형으로 선언되었기 때문에 전달되는 인자를 통해서는 T1과 T2의 자료형을 결정짓지 못한다. 따라서 이러한 경우에는 템플릿 함수의 호출형식을 완전히 갖춰서 호출해야 한다.

함수 템플릿의 특수화

상황에 따라서 템플릿 함수의 구성방법에 예외를 둘 필요가 있는데 이 때 사용되는 것이 '함수 템플릿의 특수화' 이다.
예시를 통해서 살펴보자
SpecialFunctionTemplate.cpp

#include <iostream>
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;
}

만약 특수화가 없고 T Max와 같이 템플릿 함수만 존재하였다면 문자열과 같은 대상을 호출할 경우 그 결과에 대해서는 아무런 의미도 부여할 수 없기 떄문에 다음과 같이 char과 const char형 에 대해서 특수화를 시켜주는 것이 좋다.


13-2 클래스 템플릿(Class Template)

함수를 템플릿으로 정의했듯이 클래스 또한 템플릿으로 정의가 가능하다. 이렇게 정의된 템플릿을 클래스 템플릿이라고 한다.

클래스 템플릿의 정의

PointClassTemplate.cpp

#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;
}

클래스 또한 템플릿으로 만들어서 사용하는 모습을 볼 수 있다. 하지만 이러한 템플릿 클래스의 경우 객체를 생성할 때 int 와 double등의 자료형 정보를 생략이 불가능하다.

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

PointClassTemplateFuncDef.cpp

#include <iostream>
using namespace std;

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

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

위의 예제는 클래스 템플릿의 선언과 정의를 분리한 모습을 보여주고 있다.일반적인 클래스의 정의와 마찬가지로 매개변수의 디폴트 값은 클래스 템플릿내에만 표시한다. 또한 생성자를 외부에 정의할 경우 이니셜라이저를 외부 생성자에만 삽입한다. template typename또한 밖에다 써주어야하며 빼먹었을 경우 컴파일러가 T가 무엇인지 알 수 없기 때문에 에러를 발생시킨다.

클래스 템플릿에서 파일을 나누는 경우

파일을 분리하여 작성 시 일반적으로 선언을 헤더부분에, 정의를 소스파일 부분에 작성을 하게되는데 이러한 클래스 템플릿에 대한 정보가 부족해질 수 있어서 일반적으론 헤더부분에 생성자와 멤버함수의 정의를 같이 넣거나 메인함수 소스파일에 #include "소스파일.cpp"를 같이 넣어서 컴파일 에러를 해결한다고 한다.

profile
It is possible for ordinary people to choose to be extraordinary.

0개의 댓글