728x90
C++에서 **클래스 템플릿(class template)**은 여러 데이터 타입에 대해 동일한 클래스를 정의할 수 있게 해주는 기능입니다. 이를 통해 코드의 재사용성과 유연성을 높일 수 있으며, 다양한 데이터 타입에 대해 동일한 로직을 적용할 수 있습니다.
기본 개념
클래스 템플릿은 template 키워드를 사용하여 정의되며, **타입 매개변수(type parameter)**를 사용해 클래스의 멤버 변수와 메서드의 타입을 동적으로 결정합니다.
기본 문법
template <typename T>
class ClassName {
public:
T memberVariable; // 템플릿 타입을 사용하는 멤버 변수
ClassName(T value) : memberVariable(value) {} // 생성자
T getValue() const { // 템플릿 타입을 사용하는 멤버 함수
return memberVariable;
}
};
예제
1. 기본 클래스 템플릿
#include <iostream>
template <typename T>
class Box {
public:
T value;
Box(T v) : value(v) {}
T getValue() const {
return value;
}
};
int main() {
Box<int> intBox(123);
Box<double> doubleBox(45.67);
std::cout << "intBox value: " << intBox.getValue() << std::endl; // 123
std::cout << "doubleBox value: " << doubleBox.getValue() << std::endl; // 45.67
return 0;
}
2. 다중 타입 매개변수
클래스 템플릿은 여러 타입 매개변수를 지원합니다.
#include <iostream>
template <typename T, typename U>
class Pair {
public:
T first;
U second;
Pair(T f, U s) : first(f), second(s) {}
void display() const {
std::cout << "First: " << first << ", Second: " << second << std::endl;
}
};
int main() {
Pair<int, double> p(1, 2.5);
p.display(); // First: 1, Second: 2.5
return 0;
}
3. 템플릿 기본값
템플릿 매개변수에 기본값을 설정할 수 있습니다.
#include <iostream>
template <typename T = int>
class Container {
public:
T value;
Container(T v) : value(v) {}
T getValue() const {
return value;
}
};
int main() {
Container<> defaultContainer(10); // 기본값(int) 사용
Container<double> doubleContainer(3.14);
std::cout << "Default Container: " << defaultContainer.getValue() << std::endl; // 10
std::cout << "Double Container: " << doubleContainer.getValue() << std::endl; // 3.14
return 0;
}
추가 주제
1. 템플릿 특수화
특정 타입에 대해 동작을 변경하려면 명시적 특수화를 사용할 수 있습니다.
#include <iostream>
template <typename T>
class Printer {
public:
void print(T value) {
std::cout << "Value: " << value << std::endl;
}
};
// 특수화
template <>
class Printer<char> {
public:
void print(char value) {
std::cout << "Character: " << value << std::endl;
}
};
int main() {
Printer<int> intPrinter;
Printer<char> charPrinter;
intPrinter.print(42); // Value: 42
charPrinter.print('A'); // Character: A
return 0;
}
2. 부분 특수화
부분 특수화는 템플릿의 일부 조건에서 동작을 변경하는 데 유용합니다.
#include <iostream>
template <typename T, typename U>
class Pair {
public:
void display() {
std::cout << "Generic Pair" << std::endl;
}
};
// 부분 특수화: 두 타입이 동일한 경우
template <typename T>
class Pair<T, T> {
public:
void display() {
std::cout << "Homogeneous Pair" << std::endl;
}
};
int main() {
Pair<int, double> genericPair;
Pair<int, int> homogeneousPair;
genericPair.display(); // Generic Pair
homogeneousPair.display(); // Homogeneous Pair
return 0;
}
3. 클래스 템플릿과 상속
템플릿 클래스는 상속 관계에서도 활용 가능합니다.
#include <iostream>
template <typename T>
class Base {
public:
void display() {
std::cout << "Base class" << std::endl;
}
};
template <typename T>
class Derived : public Base<T> {
public:
void display() {
std::cout << "Derived class" << std::endl;
}
};
int main() {
Derived<int> derived;
derived.display(); // Derived class
return 0;
}
4. 템플릿 매개변수 제약 (C++20)
C++20에서는 **컨셉(Concept)**을 사용해 타입 매개변수에 제약 조건을 추가할 수 있습니다.
#include <concepts>
#include <iostream>
template <typename T>
requires std::integral<T> // T는 정수 타입이어야 함
class IntegerBox {
public:
T value;
IntegerBox(T v) : value(v) {}
};
int main() {
IntegerBox<int> validBox(42); // OK
// IntegerBox<double> invalidBox(3.14); // 컴파일 에러
std::cout << "ValidBox value: " << validBox.value << std::endl;
return 0;
}
장점
- 코드 재사용성: 여러 데이터 타입에 대해 동일한 클래스 로직을 사용할 수 있습니다.
- 유연성: 다양한 타입을 다룰 수 있어 코드 작성이 더욱 효율적입니다.
- 타입 안전성: 컴파일 타임에 타입 검사가 이루어져, 런타임 오류를 줄일 수 있습니다.
결론
클래스 템플릿은 C++에서 강력하고 유연한 기능으로, 다양한 데이터 타입을 효율적으로 처리할 수 있습니다. 특히 템플릿 특수화, 상속, C++20의 컨셉과 결합하면 더욱 강력한 도구로 활용할 수 있습니다. 코드를 재사용하면서도 안전성과 확장성을 모두 충족시킬 수 있는 필수 기능입니다.
728x90
'C++' 카테고리의 다른 글
[C++] 클래스 템플릿의 부분 특수화(partial specialization)와 명시적 특수화(explict specialization) (0) | 2024.11.25 |
---|---|
[C++] using키워드 (0) | 2024.11.24 |
[C++] decltype(타입 결정자) (22) | 2024.11.20 |
[C++] 함수 템플릿(function template) (23) | 2024.11.19 |
[C++] merge 함수 (0) | 2024.11.18 |