포스트

[C++] 템플릿에 대해서

템플릿

C++에서 제네릭 프로그래밍의 기초인 템플릿은 쉽게 말해 구체적인 타입을 명시하지 않아도 클래스 또는 함수를 정의할 수 있게 만들어주는 틀이다.
똑같은 기능을 가진 함수나 클래스를 타입 별로 2개, 3개… 작성하는 것은 초보 개발자가 봐도 이거 아닌 것 같은데? 라고 생각을 할 것이다.
아마 C++에서 템플릿을 제일 처음 만나는 경우는 std::vector를 사용할 때일 것 같은데 vector 여기서 T에 int나 char을 입력하면 그냥 타입만 바꿨을 뿐인데 간편하게 다른 자료형도 담을 수 있게 된다. 이것이 바로 템플릿의 개념이다.

함수 템플릿

함수 템플릿은 함수를 작성할 때 기능은 명시하되, 자료형을 모호하게 두는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 다음 두 함수는 자료형만 다른 같은 기능을 하는 함수인데, 템플릿이 없으면 귀찮게 두 번 작성해야 한다
int sum(int a, int b)
{
  return a + b;
}

double sum(double a, double b)
{
  return a + b;
}

// 다음과 같이 템플릿을 쓰면 하나만 써도 함수를 호출할 때 컴파일러가 T 자리에 있는 자료형을 해석해 실행된다
template<typename T>
T sum(T a, T b)
{
  return a + b;
}

클래스 템플릿

함수 템플릿과 마찬가지로 클래스도 자료형을 모호하게 표현할 수 있다 여기서 멤버 함수를 클래스 안에 정의할 때와 밖에서 정의할 때가 갈리는데 클래스 안에서 정의할 때는 그냥 함수 템플릿과 똑같이 기능을 구현하면 된다.
만약 클래스 밖에서 멤버 함수를 정의한다 하면 멤버 함수 및 생성자 마다 template 선언을 해줘야 한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template<class T>  // typename과 같음
class Circle
{
  public:
    Circle();
    Circle(T radius);

    T GetRadius();
    void SetRadius(T radius);
  private:
    T radius;
}

...

template<typename T>
void Circle<T>::SetRadius(T radius)
{
  this.radius = radius;
}

...

Circle<int> c;

보시다시피 번거로운 과정이 있다.

템플릿 특수화

템플릿 특수화는, 템플릿을 사용할 때 특수한 자료형에 대해서는 다른 처리를 하고 싶을 때 사용하는 기술이다.
만약 템플릿으로 두 매개변수를 더하는 함수를 작성했을 때 만약 문자열이 들어온다면 문자열을 합 하지 못하게 하고 싶으면?
먼저 템플릿으로 기본적으로 더하는 함수를 정의하되, 같은 함수를 특별한 자료형에 대해서 한번 더 정의해주면 된다.

1
2
3
4
5
6
7
8
9
10
11
template<typename T>
T sum(T a, T b)
{
  return a + b;
}
template<>
char* sum<char*> (char* s1, char* s2)
{
  cout << "문자열은 더할 수 없습니다\n";
  return s1;
}

이렇게 함수를 오버로딩하듯이 재정의해주면 된다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.