[C++STL] 템플릿 - 함수 템플릿

박남호·2022년 12월 2일
0

함수 오버로딩을 이용하면 파라메타만 다른 함수들을 정의할 수 있다. 아래 예제에서는 int, double, char* 파라메타만 다른 세 함수를 정의하고 있다.

#include <iostream>
using namespace std;
void Print(int a, int b) 
{
	cout << a << " , " << b << endl;
}
void Print(double a, double b) 
{
	cout << a << " , " << b << endl;
}
void Print(const char* a, const char* b)
{
	cout << a << " , " << b << endl;
}
int main()
{	
	Print(10, 20);
	Print(0.123, 1.123);
	Print("ABC", "abcde");
	return 0;
}

하지만 이건 어떤 타입의 파라미터가 들어올지 알고있는 상황에서는 사용할 수 있지만 클라이언트에서 사용자 정의 타입을 결정해야한다면 함수 오버로딩으로는 해결할 수 없다. 이런 문제를 해결하기 위해 템플릿의 개념이 나왔다. 템플릿 함수를 사용하면 컴파일러는 클라이언트의 함수 호출 인자 타입을 보고 템플릿 함수의 파라미터 타입을 정하여 실제 함수인 템플릿 인스턴스 함수를 만들어 낸다.

함수 템플릿은 함수 앞에 template< T > 키워드를 붙이면 된다. 또한, 클라이언트가 매개변수 타입을 결정하도록 타입을 일반화 <T 타입>하면 된다. 아래 예제는 위 함수 오버로딩 예제를 함수 템플릿 예제로 변환한 예제이다.

#include <iostream>
using namespace std;
template<typename T>
void Print(T a, T b) 
{
	cout << a << "," << b << endl;
}
int main()
{	
	Print(10, 20);
	Print(0.123, 1.123);
	Print("ABC", "abcde");
	return 0;
}

클라이언트가 직접 타입을 지정하고 명시적으로 함수를 호출할 수 있다. 아래 예제는 명시적으로 호출한 예제이다.

#include <iostream>
using namespace std;
template<typename T>
void Print(T a, T b) 
{
	cout << a << "," << b << endl;
}
int main()
{	
	Print<int>(10, 20);
	Print<double>(0.123, 1.123);
	Print<const char*>("ABC", "abcde");
	return 0;
}

연습 예제로 배열을 출력하기 위한 함수 템플릿 예제를 보려고한다.

#include <iostream>
using namespace std;

template<typename T,int size>
void PrintArray(T* arr) 
{
	for (int i = 0; i < size; i++) {
		cout << "[" << i <<"]"<<arr[i]<< endl;
	}
}
int main()
{	
	int arr1[5] = { 10,20,30,40,50 };
	double arr2[3] = { 1.1,2.2,3.3 };
	PrintArray<int, 5>(arr1);
	PrintArray<double, 3>(arr2);
	return 0;
}

배열 함수 템플릿에서 중요하게 볼 포인트는 선언 시 template<typename T, int size>와 같이 size를 파라미터로 받는다는 것과 호출시에도 PrintArray<int, 5>(arr1);처럼 명시적으로 호출한다.

마지막으로 함수 템플릿 특수화에 대해 설명하고 마치려고한다. 클래스 객체와 같이 일반 연산이 불가능한 파라미터를 사용하는 경우이다. 예제를 먼저 보겠다.

#include <iostream>
using namespace std;
class Point
{
	int x; int y;
public:
	explicit Point(int _x = 0, int _y = 0) :x(_x), y(_y) {}
	void Print() const { cout << x << ',' << y << endl; }
};

template<typename T>
void Print(T a) 
{
	cout << a << endl;
}
template<>
void Print(Point a)
{
	cout << "Print 특수화 버전 : ";
	a.Print();
}
int main()
{	
	int n = 10;
	double d = 2.5;
	Point pt(2, 3);

	Print(n);
	Print(d);
	Print(pt);
	return 0;
}

Point 객체는 일반 템플릿 함수에서는 cout을 처리할 수가 없다. 그래서 특수화 버전의 템플릿 함수를 사용해서 명시적으로 파라미터를 Point a로 받는다. n과 d는 일반 템플릿 함수를 호출하고 pt는 특수화 템플릿 함수를 호출한다.

profile
NamoPark

0개의 댓글