오늘 우리의 목표는 아래와 같다.
• 템플릿을 사용하여 타입 독립적인 코드를 작성할 수 있다.
• 재사용성을 높이는 프로그래밍 방식을 학습한다.
프로그래밍에서 두 수를 더하는 계산기를 생각해보자.
실세계 에서는 그냥 두 수를 더한다고 생각하는 반면, 프로그래밍 측면에서는 변수의 타입이 존재하므로 int,를 더하는 동작, float를 더하는 동작 모두 다르다.
오늘 배울 템플릿 문법을 사용하면, 타입에 의존하지 않는 프로그래밍이 가능하다.

템플릿에 들어가기 앞서 함수 오버로딩에 대해 공부해 보자. C언어와 다르게 C++은 특정한 규칙만 지키면 동일한 이름의 함수를 만들 수 있다. 왜냐하면 C언어의 경우엔 함수의 이름만을 가지고 판단하나, C++은 함수의 이름에 추가로 매개변수를 가지고 판단하기 때문이다.
하지만 함수 오버로딩이 되려면 이름이 같음에도 구분이 명확해야한다.
조건은 아래와 같다.
1. 매개변수 타입이 다른 경우
2. 매개변수의 개수가 다른 경우
예시 코드를 보자
우선, 매개변수 타입이 다른 경우 함수 오버로딩부터 살펴보자.
#include <iostream>
using namespace std;
// int 타입 출력
void display(int value) {
cout << "정수 값: " << value << endl;
}
// double 타입 출력
void display(double value) {
cout << "실수 값: " << value << endl;
}
// string 타입 출력
void display(string value) {
cout << "문자열 값: " << value << endl;
}
int main() {
display(10); // int형 호출
display(3.14); // double형 호출
display("Hello!"); // string형 호출
return 0;
}
다음으로 매개변수 개수가 다른 함수 오버로딩이다.
#include <iostream>
using namespace std;
// 매개변수 1개
void printSum(int a) {
cout << "하나의 값: " << a << endl;
}
// 매개변수 2개
void printSum(int a, int b) {
cout << "두 값의 합: " << a + b << endl;
}
// 매개변수 3개
void printSum(int a, int b, int c) {
cout << "세 값의 합: " << a + b + c << endl;
}
int main() {
printSum(10); // 매개변수 1개
printSum(10, 20); // 매개변수 2개
printSum(10, 20, 30); // 매개변수 3개
return 0;
}
함수 오버로딩이 되려면, 호출되는 함수가 분명해야 한다.
애매모호한 경우에는 컴파일 에러가 발생한다.
대표적인 애매모호한 경우는 다음과 같다.
1. 반환 타입만 다를 경우
2. 디폴트 매개변수의 모호성
3. 매개변수의 타입만 포인터와 배열로 다른 경우
예시 코드를 보자.
반환 타입만 다른 경우 함수 오버로딩이다.
#include <iostream>
using namespace std;
// 정수 반환
int getValue() {
return 42;
}
// 동일한 함수 이름으로 반환 타입만 다름 -> 컴파일 에러 발생
double getValue() {
return 3.14;
}
int main() {
cout << getValue() << endl; // 어떤 함수를 호출해야 할지 모호
return 0;
}
다음으로 디폴트 매개변수가 모호한 함수 오버로딩이다.
#include <iostream>
using namespace std;
void printMessage(string message = "Default") {
cout << "문자열 출력: " << message << endl;
}
void printMessage() {
cout << "기본 메시지 출력" << endl;
}
int main() {
printMessage(); // 모호성 발생 -> 컴파일 에러
return 0;
}
마지막으로 매개변수의 타입만 포인터와 배열로 다른 함수 오버로딩이다.
#include <iostream>
using namespace std;
void process(int* arr) {
cout << "포인터를 처리하는 함수" << endl;
}
void process(int arr[]) {
cout << "배열을 처리하는 함수" << endl;
}
int main() {
int numbers[] = {1, 2, 3};
process(numbers); // 포인터와 배열 구분 불가 -> 컴파일 에러
return 0;
}
함수 오버로딩이 이름이 같은 함수를 정의할 수 있는 것인건 알겠는데...
어떤 함수가 호출될까? 아래와 같은 순서를 기억하면 된다.


#include <iostream>
using namespace std;
void process(int value) {
cout << "(int) 호출" << value << endl;
}
void process(int value, int value2) {
cout << "(int, int) 호출" << value * value2 << endl;
}
void process(float value) {
cout << "(float) 호출" << value << endl;
}
void process(float value, float value2) {
cout << "(float, float) 호출" << value * value2 << endl;
}
int main() {
process(10); //(int) 호출
process(3, 4.3);//(int, int) 호출
return 0;
}
템플릿은 일반화된 코드를 작성할 수 있는 문법이다.
내가 정의할 함수 위에 아래를 추가해주면 된다.
template <typename T>
이 의미는 어떤 타입이 올지 모르겠으나, 그 타입을 T라고 하겠다 라는 의미이다.
이후에는 일반화 할 타입에 실제 타입대신에 T를 작성해주면 된다.

두 수를 더하는 함수를 템플릿으로 구현
#include <iostream>
using namespace std;
template <typename T>
T add(T x, T y) {
return x + y;
}
int main() {
cout << add(3, 4) << endl; // 정수형 덧셈
cout << add(3.3, 4.2) << endl; // 실수형 덧셈
return 0;
}
두 값중 큰 값을 반환하는 함수를 템플릿으로 구현
#include <iostream>
using namespace std;
template <typename T>
T getMax(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << "Max of 10 and 20: " << getMax(10, 20) << endl; // 정수형
cout << "Max of 3.5 and 2.7: " << getMax(3.5, 2.7) << endl; // 실수형
cout << "Max of 'a' and 'z': " << getMax('a', 'z') << endl; // 문자형
return 0;
}
배열의 합을 계산하는 함수를 템플릿으로 구현
#include <iostream>
using namespace std;
template <typename T>
T sumArray(T arr[], int size) {
T sum = 0;
for (int i = 0; i < size; ++i) {
sum += arr[i];
}
return sum;
}
int main() {
int intArr[] = {1, 2, 3, 4, 5};
double doubleArr[] = {1.1, 2.2, 3.3, 4.4};
cout << "Sum of int array: " << sumArray(intArr, 5) << endl; // 정수형 배열
cout << "Sum of double array: " << sumArray(doubleArr, 4) << endl; // 실수형 배열
return 0;
}
값을 서로 교환 하는 함수를 템플릿으로 구현
#include <iostream>
using namespace std;
template <typename T>
void swapValues(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
swapValues(x, y);
cout << "Swapped int values: x = " << x << ", y = " << y << endl;
double p = 3.14, q = 2.71;
swapValues(p, q);
cout << "Swapped double values: p = " << p << ", q = " << q << endl;
return 0;
}
두 값이 같은지 확인하는 함수를 템플릿으로 구현
#include <iostream>
using namespace std;
template <typename T>
bool isEqual(T a, T b) {
return a == b;
}
int main() {
cout << boolalpha; // true/false 출력 활성화
cout << "Are 10 and 10 equal? " << isEqual(10, 10) << endl; // 정수 비교
cout << "Are 3.5 and 2.7 equal? " << isEqual(3.5, 2.7) << endl; // 실수 비교
cout << "Are 'a' and 'b' equal? " << isEqual('a', 'b') << endl; // 문자 비교
return 0;
}
함수 뿐만 아니라 클래스도 역시 탬플릿화 할 수 있다.
간단하게 벡터 클래스 구현
#include <iostream>
using namespace std;
template <typename T>
class MyArray {
private:
T* arr; // 동적 배열
int capacity; // 배열의 최대 크기
int size; // 현재 원소 개수
public:
// 생성자
MyArray(int cap) : capacity(cap), size(0) {
arr = new T[capacity];
}
// 소멸자
~MyArray() {
delete[] arr;
}
// 원소 추가
void push(T value) {
if (size < capacity) {
arr[size] = value;
size++;
} else {
cout << "배열이 가득 찼습니다!" << endl;
}
}
// 맨 뒤 원소 삭제
void pop() {
if (size > 0) {
size--;
} else {
cout << "배열이 비어 있습니다!" << endl;
}
}
// 배열 출력
void print() const {
cout << "[ ";
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << "]" << endl;
}
};
자 그럼 오버로딩된 함수를 템플릿으로 변경해보자.
#include <iostream>
using namespace std;
//아래 3개의 함수를 하나의 템플릿 함수로 통합하세요
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
std::string add(const std::string& a, const std::string& b) {
return a + b;
}
//아래 테스트 코드는 변역하지 마세요
int main() {
// 정수 더하기
cout << "3 + 5 = " << add(3, 5) << endl;
// 실수 더하기
cout << "2.5 + 4.3 = " << add(2.5, 4.3) << endl;
// 문자열 합치기
cout << "\"Hello, \" + \"World!\" = " << add(string("Hello, "), string("World!")) << endl;
// 아래 코드는 컴파일 에러가 발생해야 함
// cout << add(true, false) << endl;
return 0;
}
정답 코드
#include <iostream>
using namespace std;
//아래 3개의 함수를 하나의 템플릿 함수로 통합하세요
template <typename T>
T add(T a, T b) {
return a + b;
}
//아래 테스트 코드는 변역하지 마세요
int main() {
// 정수 더하기
cout << "3 + 5 = " << add(3, 5) << endl;
// 실수 더하기
cout << "2.5 + 4.3 = " << add(2.5, 4.3) << endl;
// 문자열 합치기
cout << "\"Hello, \" + \"World!\" = " << add(string("Hello, "), string("World!")) << endl;
// 아래 코드는 컴파일 에러가 발생해야 함
// cout << add(true, false) << endl;
return 0;
}