함수 템플릿
함수 템플릿은 하나의 함수 정의로 다양한 데이터 타입에 대해 동작할 수 있도록 해주는 기능입니다. 이를 통해 코드 중복을 줄이고, 유연한 구현이 가능해집니다.
기본 예제: 값 교환
정수와 실수를 위한 별도의 스왑 함수를 작성하는 대신, 단일 템플릿으로 처리할 수 있습니다.
template <typename Type>
void Swap(Type& a, Type& b) {
Type temp = a;
a = b;
b = temp;
}
이 템플릿을 사용하면 컴파일러가 인자 타입에 따라 적절한 함수를 자동 생성합니다.
int x = 5, y = 10;
Swap(x, y); // Swap<int>() 생성
double a = 3.14, b = 2.71;
Swap(a, b); // Swap<double>() 생성
다중 타입 매개변수
여러 타입을 받는 함수 템플릿도 가능합니다.
template <typename T1, typename T2>
void Process(T1 val1, T2 val2) {
std::cout << val1 << ", " << val2 << std::endl;
}
템플릿 오버로딩
매개변수 목록이나 타입 파라미터가 다르면 템플릿 오버로딩이 가능합니다.
template <typename T>
void Display(T a, T b) { /* ... */ }
template <typename T, typename U>
void Display(T a, U b) { /* ... */ }
템플릿 우선순위
호출 시 컴파일러는 다음 순서로 선택합니다:
- 정확히 일치하는 일반 함수
- 정확히 일치하는 템플릿 함수
- 형 변환 후 일치하는 일반 함수
- 모든 경우 실패 → 에러
클래스 템플릿
클래스 템플릿은 특정 타입에 맞춰 여러 클래스를 빠르게 생성할 수 있게 해줍니다.
기본 구문
template <typename T>
class Container {
T data;
public:
Container(T value) : data(value) {}
T Get() const { return data; }
};
예시: 키-값 쌍 클래스
키와 값을 저장하는 Pair 클래스를 템플릿으로 정의합니다.
template <typename KeyType, typename ValueType>
class Pair {
private:
KeyType key;
ValueType value;
public:
Pair(KeyType k, ValueType v) : key(k), value(v) {}
bool operator<(const Pair& other) const {
return value < other.value;
}
};
// 사용 예
Pair<std::string, int> student("Alice", 25);
Pair<std::string, int> another("Bob", 28);
std::cout << (student < another) << std::endl; // 출력: 1
멤버 함수 템플릿
클래스 내부의 멤버 함수도 템플릿으로 선언할 수 있습니다.
template <typename T>
class Helper {
public:
template <typename U>
void Print(U value) {
std::cout << value << std::endl;
}
};
Helper<int> h;
h.Print(42); // Print<int>()
h.Print("hello"); // Print<const char*>()
비타입 매개변수
템플릿 파라미터로 크기 같은 상수도 사용 가능합니다.
template <typename T, size_t N>
class FixedArray {
T data[N];
public:
void Set(size_t idx, T val) { data[idx] = val; }
T Get(size_t idx) const { return data[idx]; }
};
FixedArray<int, 10> arr; // 고정 크기 배열
상속 관계
클래스 템플릿은 다른 템플릿, 일반 클래스, 또는 템플릿 클래스로부터 상속받을 수 있습니다.
// 템플릿에서 템플릿 상속
template <typename T>
class Base { };
template <typename T>
class Derived : public Base<T> { };
// 일반 클래스에서 템플릿 상속
class BaseClass { };
template <typename T>
class TemplateDerived : public BaseClass { };
친구 관계 (Friend)
템플릿 내부에서 일반 함수, 클래스, 함수 템플릿, 또는 다른 템플릿 클래스를 친구로 선언할 수 있습니다.
template <typename T>
class MyClass {
friend void FriendFunction(); // 일반 친구 함수
friend class FriendClass; // 일반 친구 클래스
friend template <typename U> void Func(U); // 함수 템플릿 친구
};
정적 멤버 변수
템플릿 내부의 정적 멤버는 각 인스턴스마다 공유되며, 개별적으로 초기화되어야 합니다.
template <typename T>
class Counter {
private:
static int instance_count;
public:
Counter() { ++instance_count; }
~Counter() { --instance_count; }
static void ShowCount() {
std::cout << "Instances: " << instance_count << std::endl;
}
};
// 정적 멤버 초기화
template <> int Counter<int>::instance_count = 0;
template <> int Counter<double>::instance_count = 0;
Counter<int> c1;
Counter<double> c2;
Counter<int>::ShowCount(); // 출력: 1
Counter<double>::ShowCount(); // 출력: 1