반응형
C++ 템플릿은 제네릭 프로그래밍(generic programming)을 가능하게 하는 강력한 도구입니다. 템플릿을 사용하면 타입에 의존하지 않는 코드를 작성할 수 있어 코드 재사용성과 유연성이 크게 향상됩니다. 이번 포스팅에서는 C++ 템플릿의 기본 개념부터 실용적인 예제까지 다루어 보겠습니다.
1. 템플릿이란 무엇인가?
템플릿은 컴파일 타임에 타입을 정할 수 있는 코드 블록을 의미합니다. 함수나 클래스 정의에서 특정 타입 대신 템플릿 매개변수
를 사용하여 다형성을 제공합니다. 이를 통해 다양한 데이터 타입에서 동작하는 일반화된 코드를 작성할 수 있습니다.
2. 함수 템플릿
함수 템플릿은 함수 정의에서 특정 데이터 타입을 일반화합니다. 가장 간단한 템플릿 형태는 다음과 같습니다:
#include <iostream>
// 함수 템플릿 정의
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << "정수 덧셈: " << add(3, 4) << std::endl;
std::cout << "실수 덧셈: " << add(3.5, 4.5) << std::endl;
return 0;
}
출력 결과
정수 덧셈: 7
실수 덧셈: 8
주요 특징
template <typename T>
는 템플릿을 선언하는 부분입니다.T
는 사용자가 제공한 타입으로 대체됩니다.- 컴파일러가 함수 호출 시점에 적절한 타입을 유추하여 템플릿을 인스턴스화합니다.
3. 클래스 템플릿
클래스 템플릿은 템플릿 매개변수를 사용하여 특정 타입에 의존하지 않는 클래스 정의를 작성할 수 있습니다.
예제: 클래스 템플릿을 이용한 스택 구현
#include <iostream>
#include <vector>
// 클래스 템플릿 정의
template <typename T>
class Stack {
private:
std::vector<T> elements;
public:
void push(T element) {
elements.push_back(element);
}
void pop() {
if (!elements.empty()) {
elements.pop_back();
}
}
T top() const {
if (!elements.empty()) {
return elements.back();
}
throw std::out_of_range("Stack is empty");
}
bool isEmpty() const {
return elements.empty();
}
};
int main() {
Stack<int> intStack;
intStack.push(10);
intStack.push(20);
std::cout << "Top of intStack: " << intStack.top() << std::endl;
intStack.pop();
std::cout << "Top of intStack after pop: " << intStack.top() << std::endl;
Stack<std::string> stringStack;
stringStack.push("Hello");
stringStack.push("World");
std::cout << "Top of stringStack: " << stringStack.top() << std::endl;
return 0;
}
출력 결과
Top of intStack: 20
Top of intStack after pop: 10
Top of stringStack: World
주요 특징
- 클래스 템플릿은
template <typename T>
로 선언합니다. - 특정 타입에 독립적인 일반화된 데이터 구조를 만들 수 있습니다.
4. 비타입(non-type) 템플릿 매개변수
C++ 템플릿은 타입뿐만 아니라 정수, 포인터 등 비타입 매개변수도 지원합니다.
예제: 배열 크기를 고정한 템플릿 클래스
#include <iostream>
// 비타입 템플릿 매개변수 사용
template <typename T, int Size>
class Array {
private:
T data[Size];
public:
T& operator[](int index) {
return data[index];
}
int size() const {
return Size;
}
};
int main() {
Array<int, 5> intArray;
for (int i = 0; i < intArray.size(); ++i) {
intArray[i] = i * 10;
}
for (int i = 0; i < intArray.size(); ++i) {
std::cout << intArray[i] << " ";
}
std::cout << std::endl;
return 0;
}
출력 결과
0 10 20 30 40
주요 특징
- 비타입 매개변수는 템플릿 정의에 고정된 값을 전달받을 수 있습니다.
- 배열과 같이 크기가 정해진 데이터 구조를 구현할 때 유용합니다.
5. 템플릿 특수화
템플릿 특수화는 특정 타입에 대해 템플릿의 동작을 맞춤화할 수 있게 합니다.
예제: 템플릿 특수화
#include <iostream>
// 기본 템플릿
template <typename T>
class Printer {
public:
void print(T value) {
std::cout << "일반 값: " << value << std::endl;
}
};
// 템플릿 특수화: 문자열 타입에 대해 맞춤화
template <>
class Printer<std::string> {
public:
void print(std::string value) {
std::cout << "문자열 값: " << value << std::endl;
}
};
int main() {
Printer<int> intPrinter;
intPrinter.print(42);
Printer<std::string> stringPrinter;
stringPrinter.print("Hello Templates!");
return 0;
}
출력 결과
일반 값: 42
문자열 값: Hello Templates!
주요 특징
- 특수화된 템플릿은
template<>
구문을 사용합니다. - 특정 타입에 대해 기본 템플릿 동작을 맞춤화할 수 있습니다.
6. 템플릿의 한계와 주의점
- 컴파일 시간 증가: 템플릿은 컴파일 타임에 인스턴스화되므로 컴파일 시간이 늘어날 수 있습니다.
- 디버깅 어려움: 템플릿 오류는 디버깅이 어렵고 복잡한 컴파일러 메시지를 생성할 수 있습니다.
- 코드 크기 증가: 사용된 타입별로 인스턴스화되기 때문에 코드 크기가 증가할 수 있습니다.
7. 결론
템플릿은 C++의 핵심 기능 중 하나로, 코드의 재사용성과 유연성을 극대화합니다. 함수 템플릿, 클래스 템플릿, 비타입 매개변수, 템플릿 특수화 등 다양한 템플릿 기법을 활용하면 더 나은 코드 설계가 가능합니다. 템플릿을 익히고 실무에서 활용해 보세요!
반응형
'cpp' 카테고리의 다른 글
C++ 예외 처리 (Exception Handling) (0) | 2024.12.20 |
---|---|
C++ STL(Standard Template Library) (0) | 2024.12.20 |
C++ 네임스페이스(namespace) (0) | 2024.12.20 |
C++ 연산자 오버로딩 (Operator Overloading) (0) | 2024.12.19 |
C++ 상속과 다형성 (0) | 2024.12.19 |