함수 탬플릿
인자로 들어오는 변수타입이나 지역변수타입, 리턴타입을 특정할 수 없을때, 혹은 특정하고 싶지 않을때 쓰인다.
typename을 통해 타입을 추상적으로 지정하여 작성한 함수의 형틀이라고 볼 수 있다.
(함수 템플릿은 어디까지나 함수를 만들기 위한 형틀에 지나지 않으며 그 자체가 함수인 것은 아니다.)
(컴파일러는 함수 템플릿 정의문으로부터 앞으로 만들어질 함수의 모양만 기억하며 실제 함수가 호출될
때 타입에 맞는 함수를 작성한다.)
예를들어 더하기 연산을 하는 함수를 작성하고 싶은데 int, float, double등 모든
자료형에 대응하려면 각 자료형마다 함수를 작성해야한다.
만약 모든 자료형을 받는 함수를 만들면 이 불편함을 해결할 수 있을 것이다.
그 때 쓰이는 것이 함수 탬플릿이다.
하지만 모든 자료형을 받는다고 하면, 자료형마다 연산이 다르므로 오류가 날때가 있을 것이다.
이를 해결해주는 것이 함수 탬플릿의 특수화이다.
예외 케이스에 해당하는 자료형에 대해서는 다른 로직을 적용하는 것이다.
예를들어 int 는 서로 더할 수 있지만, 포인터는 서로 더할 수 없다.
따라서 포인터형에 대해서는 다른 로직을 적용해야한다. 이때 쓰이는 것이 함수 탬플릿의 특수화이다.
template <typename T>
T Add(T _a, T _b)
{
return _a + _b;
}
template <typename T1, typename T2, typename T3>
T3 Add(T1 _a, T2 _b)
{
return _a + _b;
}
함수 탬플릿
template <>
char* Add(char* _a, char* _b)
{
int iLen = strlen(_a) + strlen(_b);
char* pStr = new char[iLen + 1];
strcpy_s(pStr, iLen + 1, _a);
strcat_s(pStr, iLen + 1, _b);
return pStr;
}
함수 탬플릿의 특수화
여기서 의문이 들 수 있다.
특수화를 쓰지않고
char* Add(char* _a, char* _b)
{
int iLen = strlen(_a) + strlen(_b);
char* pStr = new char[iLen + 1];
strcpy_s(pStr, iLen + 1, _a);
strcat_s(pStr, iLen + 1, _b);
return pStr;
}
이런 식으로 오버로딩하면 되지 않느냐?
하지만 이러면 함수호출 우선순위에 있어서 문제가 생긴다.
오버로딩한 함수는 일반함수다.
만약
Add("sdf", "grg")
처럼 함수를 호출하면
T Add(T _a, T _b)
{
return _a + _b;
}
과
char* Add(char* _a, char* _b)
{
int iLen = strlen(_a) + strlen(_b);
char* pStr = new char[iLen + 1];
strcpy_s(pStr, iLen + 1, _a);
strcat_s(pStr, iLen + 1, _b);
return pStr;
}
중에서 어떤 함수를 호출할 것인가?
알 수 없다. 이는 컴파일러에 따라 달라진다.
때문에 특수화가 필요한 것이다.
특수화된 함수탬플릿은 항상 함수탬플릿보다 우선적으로 실행된다.
탬플릿 함수
탬플릿 함수는 함수 탬플릿에 의해 생성된 실제 함수다.
탬플릿 함수는 컴파일 과정 중 해당 함수가 어떤 자료형으로 호출될지 결정될때 typename이
해당 자료형으로 치환되는 식으로 만들어진다.
만들어진 함수는 같은 자료형에 대해서는 재사용되고, 다른 자료형을 받게되면 새로 생성된다.
탬플릿함수를 호출할때는 기본적으로 함수명 뒤에, 사용할 자료형을 <>안에 명시해야한다.
Add<int>(10, 20)
그러나 인자로 들어오는 값의 타입을 통해 어떤 함수 탬플릿을 말하는 것인지 알 수 있다면
생략할 수 있다.
Add(10, 20)
그렇지 않은 경우는 이러하다.
Add<int, float, double>(10, 3.14f)
이 경우 리턴타입이 double이라는 것은 인자의 타입을 통해서는 알 수 없으므로 명시적으로 타입을
지정해줘야한다.
'C++' 카테고리의 다른 글
STL - vector (0) | 2020.10.27 |
---|---|
STL (0) | 2020.10.27 |
인라인함수, 매크로함수 (0) | 2020.10.27 |
타입 캐스팅 (0) | 2020.10.27 |
비트연산으로 flag주기 (0) | 2020.10.27 |