본문 바로가기
스터디/C++

[ C++ ] 함수 템플릿(Function Template)과 템플릿 함수(Template Function)

by 알 수 없는 사용자 2019. 11. 29.

Template. 형판, 형틀 어떤 특정한 모양을 만들기 위해 만들어진 틀을 말한다.

 

즉, 함수 템플릿(Function Template)함수를 만드는 도구를 의미한다. 

함수를 만드는 도구는 무엇으로 이뤄져서 만들지는 정하지는 않는다.

그래서 함수 템플릿이 만들어 내는 함수의 자료형도 결정되어 있지 않는다.

 

예를 보자.

int Adder(int n1, int n2)
{
	return n1 + n2;
}

위의 함수의 기능은 덧셈이고, 대상 자료형(파라미터와 리턴 값)은 int형 데이터이다.

 

이러한 함수를 만들어 낼 수 있는 템플릿(Template)은 다음과 같다.

T Adder(T n1, T n2)
{
	return n1 + n2;
}

위의 함수의 기능은 덧셈이고, 대상 자료형(파라미터와 리턴 값)은 결정되어 있지 않다.

 

여기서 T는 자료형을 결정짓지 않겠다는 의미로 사용한 것이기에, 우리는 컴파일러가 알기 위해서 상단에

template <typename T>를 붙여야 한다.

template <typename T>
T Adder(T n1, T n2)
{
	return n1 + n2;
}

이렇게 완성된 함수를 함수 템플릿(Function Template)이라고 한다.

 

* Tip

template <typename T> 말고도 template <class T>를 사용할 수도 있습니다.

둘 다 흔히 사용이 되니, 두 가지 선언은 같은 의미라는 것을 기억하자.

C++의 초창기에는 템플릿의 선언에 키워드 class만 사용할 수 있었는데, 클래스의 선언에 사용되는 키워드와 동일하다는 지적에 의해서 이후에 typename이라는 키워드도 추가되었다. 그래서 여전히 키워드 class를 사용하는 사람들도 있기 마련이다. typename보다 class가 입력하기 더 편하기 때문이다. T 또한 다른 문자를 사용할 수 있다.

T는 template에서 따온 것이라고 유추된다.

 

 

그럼 함수 템플릿의 활용 예제를 보자.

 

 

14행의 Adder<int>(1,2)의 뜻은

"T를 int로 해서 만들어진 Adder 함수를 호출한다."이다.

 

그럼 컴파일러는 14행을 보고 다음의 함수를 하나 만든다.

int Adder(int n1, int n2)
{
	return n1 + n2;
}

그리고 15행를 보고 다음의 함수를 하나 만든다.

double Adder(double n1, double n2)
{
	return n1 + n2;
}

 

그렇다고 매 호출 문장마다 함수를 만드는 것이 아니라, 한번 함수가 만들어지면 그다음에는 만들어진 함수를 호출할 뿐 새로 함수를 만들지는 않는다.

 

16행 같은 경우에는 T가 int인 함수를 호출하면서 double형 실수를 전달하니, 그 과정에서 값 손실이 발생한 것이다.

 

그리고 함수 템플릿을 기반으로 만들어진 함수는 다음과 같이 표현하는 것이 더 정확하다.

int Adder<int>(int n1, int n2)
{
	return n1 + n2;
}
double Adder<double>(double n1, double n2)
{
	return n1 + n2;
}

 

템플릿 함수를 호출할 경우에 일반 함수처럼 호출해도 된다.

 

Adder옆에 대상 자료형을 붙이지 않았기 때문에, 전달되는 인자의 자료형을 참조하여 호출될 함수의 유형을 컴파일러가 결정한다.

 

즉, Adder(1.5, 2.5)를 보고 컴파일러는

전달되는 인자의 자료형이 double형이니 함수 템플릿의 T가 double이 되어야 값 손실 없이, 인자를 전달받을 수 있겠다!라고 판단한다.

 

 

그럼 템플릿 함수는 무엇일까? 일단 함수 템플릿을 다시 보자.

template <typename T>
T Adder(T n1, T n2)
{
	return n1 + n2;
}

 

우리는 이 템플릿을 기반으로 컴파일러가 만들어내는 함수들을 가리켜서 템플릿 함수(Template Function)이라고 한다.

 

int Adder<int>(int n1, int n2)
{
	return n1 + n2;
}
double Adder<double>(double n1, double n2)
{
	return n1 + n2;
}

반면 <int>와 <double>은 일반 함수가 아닌, 컴파일러가 만들어낸 템플릿 기반의 함수임을 표시한 것이다.

 

정리하자면,

 

함수 템플릿은 함수를 만드는 데 사용되는 템플릿!

템플릿 함수는 템플릿을 기반으로 만들어진 함수!

이다.

 

즉, 템플릿을 기반으로 만들어진, 호출이 가능한 함수임을 강조한 것이다. 

템플릿 함수는 일반 함수와 구분이 되는데, 두 가지 모두 함께 존재하기 위함이다.

 

아래의 예제를 보자.

 

Adder(1,2)에서 일반 함수인 Adder을 호출하였고,

Adder<int>(1,2)에서 템플릿 함수로 Adder을 호출하였다.

 

이렇게 템플릿 함수를 Adder(1,2)로 호출할 수 있지만,

일반 함수가 호출될 수 있으니, <int>와 같은 대상 자료형을 적는 것을 권한다.

 

 

첨언은 하자면 C#에서 template과 유사한 일반화 프로그래밍이 있다. 일반화(Generalization)는 템플릿과 같이 자료형들을 보통 문자 T로 묶어서 자료형이 결정되어 있지 않는 형태이다.

 

이렇듯 템플릿 함수는 컴파일러에 의해서 생성된 함수이기 때문에 생성된 함수(Generated Function)이라고 한다.