Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C++] 함수 템플릿과 특수화(Specialization) 본문

Programming/C++

[Programming/C++] 함수 템플릿과 특수화(Specialization)

scii 2021. 2. 6. 23:55

함수 템플릿과 템플릿 함수

다음의 정의를 가리켜 '함수 템플릿(Function Template)' 이라 한다.

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

반면 위의 템플릿을 기반으로 컴파일러가 만들어 내는 다음 유형의 함수들을 가리켜 '템플릿 함수(Template Function)' 이라 한다.

int Add<int>(int a, int b) {
  return num1 + num2;
}

double Add<double>(double num1, double num2) {
  return num1 + num2;
}

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

  • 함수 템플릿
    • 함수를 만드는데 사용되는 템플릿
  • 템플릿 함수
    • 템플릿을 기반으로 만들어진 함수
템플릿 함수의 또 다른 표현

'템플릿 함수'는 컴파일러에 의해 생성된 함수이기 때문에 '생성된 함수(Generated Function)'으로도 불린다.
'템플릿 클래스' 역시 '생성된 클래스(Generated Class)'라고도 불린다.

둘 이상의 형(Type)에 대한 템플릿 선언

템플릿의 정의에는 다양한 자료형의 선언이 가능할 뿐만 아니라, 둘 이상의 형(type)에 대해서 템플릿을 선언할 수도 있따.

template <typename T1, typename T2>
void ShowData(double num) { 
  cout << (T1)num << ", " << (T2)num << endl;
}

int main(void) {
  ShowData<char, int>(65);
  ShowData<short, double>(68.8);
  
  return 0;
}

위에서 보듯이 쉼표를 이용해 둘 이상의 템플릿 타입을 명시할수 있다. 그리고 함수 템플릿의 매개변수 조차도 기본 자료형으로 선언될 수 있다.

참고로 위의 문자을 아래처럼 대신할 수 있다.

cout << T1(num) << ", " << T2(num) << endl;

C++에서는 데이터에 소괄호를 묶는 형태로 형 변환을 명령할 수 있다. 아래의 형 변환문은 완전히 일치한다.

int num = (int)3.14;

int num = int(3.14);
typename 키워드 대신 class 키워드를 사용할 수 있다.

함수 템플릿의 특수화(Specialization)

#include <iostream>

#pragma warning(disable: 4996)

using std::cout;
using std::cin;
using std::endl;

template <typename T>
T Max(const T a, const T b) {
    return a > b ? a : b;
}

 int main(const int argc, const char* const argv[]) { 
     cout << Max<int>(11, 15) << endl;
     cout << Max<char>('T', 'Q') << endl;
     cout << Max<double>(3.5, 7.5) << endl;
     cout << Max<const char*>("Simple", "Best") << endl;

     return 0;
}

/* 결과

15
T
7.5
Simple

*/

위 예제의 함수 템플릿 Max는 인자로 전달된 두 데이터 중 큰 값을 반환하도록 정의되어 있다. 그런데 문자열을 대상으로 호출할 경우, 그 결과에 대해서는 아무런 의미도 부여할 수 없게 된다(단순히 주소 값의 비교결과가 반환). 

이렇듯 상황에 따라 템플릿 함수의 구성방법에 예외를 둘 필요가 있는데, 이 때 사용되는 것이 '함수 템플릿의 특수화(Specialization of Function Template)' 이다.

#include <iostream>

#pragma warning(disable: 4996)

using std::cout;
using std::cin;
using std::endl;


template <typename T>
T Max(const T a, const T b) {
    return a > b ? a : b;
}

// char* 형에 대해서 특수화
template <>
char* Max<char*>(char* a, char* b) {
    cout << "char* Max<char*>(char* a, char* b)" << endl;
    return strcmp(a, b) > 0 ? a : b;
}

// const char* 형에 대해서 특수화
template <>
const char* Max<const char*>(const char* a, const char* b) {
    cout << "const char* Max<const char*>(const char* a, const char* b)" << endl;
    return strlen(a) > strlen(b) ? a : b;
}


 int main(const int argc, const char* const argv[]) { 
     cout << Max<int>(11, 15) << endl;
     cout << Max<char>('T', 'Q') << endl;
     cout << Max<double>(3.5, 7.5) << endl;
     cout << Max<const char*>("Simple", "Best") << endl;

     char str1[] = "Simple";
     char str2[] = "Best";

     cout << endl;
     cout << Max<char*>(str1, str2) << endl;

     return 0;
}

/* 결과

15
T
7.5
const char* Max<const char*>(const char* a, const char* b)
Simple

char* Max<char*>(char* a, char* b)
Simple

*/

위의 예제에서 template<> 명령은 다음과 같다.

"char*형 함수는 프로그래머가 직접 제시를 하니, char*형 템플릿 함수가 필요한 경우 별도로 만들지 말고 프로그래머가 만든 템플릿 함수를 사용하라." 라는 메시지를 컴파일러에게 알리는 명령이다.

그리고 특수화하는 자료형 정보를 생략하건 생략하지 않건 그 의미하는 바에 차이는 없으나, 가급적이면 자료형 정보를 명시하는 것이 뜻을 명확히 하는 방법이 된다.

template <>
char* Max<char*>(char* a, char* b) { ... }

template <>
const char* Max<const char*>(const char* a, const char* b) { ... }
Comments