On this page
article
C++ Template Specialization
Template Specialization
- 특정 타입에 대한 템플릿을 별도로 제공하는 기법.
- 예를 들어,
vector<bool>
처럼bool
타입에 대해서만 다르게 동작하게 하고 싶을 때 사용. (bool만큼은 bit로 관리하는 게 효율적이기때문에)
종류
- primary template
template<typename T> class Vector
- specialization
template<typename T> Vecotr<bool>
- partial specialization
template<typename T> class Vecotr<T*>
유의 1. 포인터 타입 제거
#include <iostream>
#include <typeinfo>
// 기본 템플릿
template<typename T> struct remove_pointer {
static void print() {
std::cout << typeid(T).name() << std::endl;
}
};
// 특수화 버전 (포인터 타입)
template<typename T> struct remove_pointer<T*> {
static void print() {
std::cout << typeid(T).name() << std::endl;
}
};
int main() {
remove_pointer<int>::print(); // int
remove_pointer<int*>::print(); // int
}
remove_pointer<int*>
는T = int
로 매칭됨.- 포인터 타입을 제거하는 특수화 버전이 호출됨.
유의 2. Partial Specialization 시 Default Parameter 표기 금지
#include <iostream>
// Primary Template
template<typename T1, typename T2 = T1>
struct Object {
static void print() {
std::cout << typeid(T1).name() << ", " << typeid(T2).name() << std::endl;
}
};
// Partial Specialization (default parameter 표기 X)
template<typename T1, typename T2>
struct Object<T1*, T2> {
static void print() {
std::cout << typeid(T1).name() << ", " << typeid(T2).name() << std::endl;
}
};
int main() {
Object<int*>::print(); // int, int*
}
- Partial Specialization에서는 default parameter (
= T1
)를 다시 표기하지 않음. - Primary Template의 default를 그대로 사용.
사용 사례. Primary 버전만 선언하고 Specialization만 제공하기
// Primary 선언만 (정의 없음)
template<typename T, int N>
struct Object;
// Specialization만 정의
// N = 1
template<typename T>
struct Object<T, 1> {
static void info() { std::cout << "Specialization N=1" << std::endl; }
};
// N = 2
template<typename T>
struct Object<T, 2> {
static void info() { std::cout << "Specialization N=2" << std::endl; }
};
int main() {
Object<int, 1>::info(); // Specialization N=1
Object<int, 2>::info(); // Specialization N=2
// Object<int, 3> obj; // Error! primary 정의 없음
}
- Primary는 선언만 하고, 특정 조건(N=1, N=2)만 제공할 수 있음.
- 다른 경우(N=3)는 에러 발생.
std::conditional 활용
- 조건에 따라 타입을 선택하는 메타 프로그래밍 기법.
std::conditional<조건, Type1, Type2>::type
- 조건이 true면 Type1, false면 Type2 선택.
std::conditional 직접 구현
#include <iostream>
// Primary Template
template<bool Cond, typename T1, typename T2>
struct conditional {
using type = T1;
};
// Specialization (Cond = false)
template<typename T1, typename T2>
struct conditional<false, T1, T2> {
using type = T2;
};
int main() {
using T = conditional<true, int, double>::type;
std::cout << typeid(T).name() << std::endl; // int
}
- 조건에 따라 타입을 선택하는 기본적인 템플릿 메타 프로그래밍 예시.