template <typename T>
class Point {
T x, y;
};
template <> Point<int>::Point(double x, double y) {
this->x = x + 0.5; this->y = y + 0.5;
}
→ T type을 사용하는 Point 클래스 템플릿을 선언하였다.
이 클래스는 T 타입의 멤버 변수 x와 y를 가지고 있다.
생성자는 double 타입의 x와 y를 parameter로 받아 멤버 변수에 초기화한다.
→ Point< int >에 대해 생성자를 특수화하였다. double 타입의 x와 y를 parameter로 받아 각각 x + 0.5, y + 0.5를 통해 int 멤버 변수에 대입한다. (암묵적으로 내림 처리됨)
template <typename T>
class Point {
T x, y;
public:
Point(double x, double y) : x(x), y(y) {} // 생성자
};
→ T가 어떤 타입이든 상관없이, Point< T >라는 템플릿 클래스가 만들어지고 그 안의 생성자는 항상 this->x = x, this->y = y처럼 값을 그대로 저장한다.
그런데 int일 때만 다르게 하고 싶다면? 예를 들어, Point< int >일 때는 x+0.5를 하고 싶다면 특별한 버전의 생성자를 따로 만들어야 한다. 이걸 템플릿 특수화라고 부른다.
위 템플릿 클래스는 T 타입에 따라 달라지지만, 생성자의 매개변수는 항상 double이다. 즉, double 타입의 값을 받아서 T 타입의 x, y에 저장하는 구조다.
template <>
Point<int>::Point(double x, double y) {
this->x = x + 0.5;
this->y = y + 0.5;
}
이 생성자도 double을 받지만 x + 0.5 연산 후 int 타입에 저장한다. 즉, double을 받아서 내부에서 int로 변환하여 저장하는 것이다.
❓ “double 값을 받았는데, 왜 int처럼 동작해요?”
👉 "입력은 double이지만, 저장하는 멤버 변수 x, y가 int니까 자동으로 int로 바뀌어요!"
| 항목 | 설명 |
|---|---|
| 생성자 parameter | double 타입임 → 외부에서 값을 받을 때 |
| 멤버 변수 | T에 따라 달라짐 → Point<int>면 x, y는 int |
| 동작 | double 값을 받아 내부 int 멤버에 저장 (자동 형변환 발생) |
| 특수화 목적 | int일 때만 +0.5 처리 후 반올림 효과를 주려고 특수 생성자 사용 |
template <> ⚠️ 명시적 특수화
bool equal(char* s1, char* s2) { ... }
→ 여기서 <> 안에 아무 타입도 넣지 않은 이유는 이미 equal(char pointer, char pointer)라고 함수 인자에 타입이 명시되어 있어서, T = char* 이라는 것을 컴파일러가 추론할 수 있기 때문이다.
이걸 빼면 템플릿 특수화가 아니라 일반 function overloading으로 처리된다.
즉, equal(char pointer, char pointer )가 템플릿의 일부가 아니게 된다. 그래서 template <>는 반드시 필요하다.
template <typename T>
bool equal(T a, T b) {
return a == b;
}
다음과 같은 코드를 문자열용으로 특수화하였다.
template <> ⚠️ 명시적 특수화
bool equal(char* s1, char* s2) {
return !strcmp(s1, s2);
}
→ 명시적 특수화 (explicit specialization)
equal<char*>(char pointer a, char pointer b)를 따로 구현한 것으로 간주된다. 즉, 기존 템플릿 함수 equal< T >()의 한 부분이다. 컴파일러는 equal(str1, str2) 호출 시, 인자가 char type pointer면 이 특수화를 사용한다.
⚠️ template 선언 없음
bool equal(char* s1, char* s2) {
return !strcmp(s1, s2);
}
→ 일반 함수 오버로딩
equal(T a, T b)와 별개의 함수가 된다. 컴파일러는 함수 호출 시 일반 함수와 템플릿 함수 중 더 잘 맞는 것을 선택한다.
템플릿 구조를 유지하면서 특정 타입만 다르게 처리하고 싶을 때
🔹 추천 상황:
equal() 함수처럼 다양한 타입을 지원하면서도 일부 타입만 특별하게 처리하고 싶을 때
템플릿을 쓸 필요가 없거나, 템플릿 쓰는 게 오히려 복잡할 때
🔹 추천 상황:
지원해야 하는 타입이 몇 개 안 되고, 구조 통일이 필요 없을 때
| 상황 | 추천 방식 |
|---|---|
| 다양한 타입 지원, 일관된 구조 원함 | ✅ 템플릿 + 특수화 |
| 타입 몇 개만 처리, 단순 비교만 필요 | ✅ 함수 오버로딩 |