[cpp] template specialization

minjubyeon·2025년 5월 26일

cpp

목록 보기
15/26
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 멤버 변수에 대입한다. (암묵적으로 내림 처리됨)

1. Constructor Specialization

📦 일반 template class

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 class

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로 바뀌어요!"

항목설명
생성자 parameterdouble 타입임 → 외부에서 값을 받을 때
멤버 변수T에 따라 달라짐 → Point<int>x, yint
동작double 값을 받아 내부 int 멤버에 저장 (자동 형변환 발생)
특수화 목적int일 때만 +0.5 처리 후 반올림 효과를 주려고 특수 생성자 사용


2. Explicit Specialization

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() 함수처럼 다양한 타입을 지원하면서도 일부 타입만 특별하게 처리하고 싶을 때


✅ function overloading이 더 좋은 경우

템플릿을 쓸 필요가 없거나, 템플릿 쓰는 게 오히려 복잡할 때

🔹 추천 상황:
지원해야 하는 타입이 몇 개 안 되고, 구조 통일이 필요 없을 때

🔚 결론

상황추천 방식
다양한 타입 지원, 일관된 구조 원함템플릿 + 특수화
타입 몇 개만 처리, 단순 비교만 필요함수 오버로딩


profile
안녕하세요.

0개의 댓글