[C/C++] 템플릿(Template)

할랑말랑·2026년 3월 6일

C/C++

목록 보기
5/45

템플릿(Template)

템플릿은 C++에서 제네릭 프로그래밍을 가능하게 하는 강력한 기능이다. 템플릿을 사용하면 데이터 타입에 독립적인 코드를 작성할 수 있다.
(타입에 관계없이 일반화된 코드를 작성가능)

1. 템플릿이 필요한 이유

  • 템플릿 미사용 함수
// int형 두 수를 더하는 함수
int add(int a, int b)
{
    return a + b;
}

// double형 두 수를 더하는 함수
double add(double a, double b)
{
    return a + b;
}

// float형 두 수를 더하는 함수
float add(float a, float b)
{
    return a + b;
}

기능이 같은 함수도 타입만 바꿔서 여러번 작성해야한다.
이는 코드 중복과 유지보수의 어려움을 초래한다.

  • 템플릿 사용 함수
template <typename T>
T add(T a, T b)
{
    return a + b;
}

하나의 템플릿 함수로 모든 타입에 대응할 수 있습니다!

템플릿을 이용한 일반화된 함수는 위 그림과 같은 형태로 정의합니다.

이 의미는 어떤 타입이 올지 모르겠으나, 그 타입을 T라고 부르겠다는 의미입니다.
이후에는 일반화하려는 타입 자리에 실제 타입 대신 T를 사용하면 됩니다.

  • 배열 출력 함수
template <typename T>
void printArray(T arr[], int size)
{
    for(int i = 0; i < size; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main()
{
    int intArr[] = {1, 2, 3, 4, 5};
    double doubleArr[] = {1.1, 2.2, 3.3};

    printArray(intArr, 5);      // 1 2 3 4 5
    printArray(doubleArr, 3);   // 1.1 2.2 3.3
    return 0;
}
  • 다중타입 매개 변수 함수
template <typename T1, typename T2>
void printPair(T1 first, T2 second)
{
    cout << "First: " << first << ", Second: " << second << endl;
}

int main()
{
    printPair(10, 3.14);      // First: 10, Second: 3.14
    printPair("Hello", 100);  // First: Hello, Second: 100
    return 0;
}

2. 클래스 템플릿

  • 클래스 템플릿으로 배열을 일반화하여 원소 추가 삭제
// 목적: 클래스 템플릿으로 배열을 일반화하여 원소 추가 및 삭제 기능 구현하기
#include <iostream>
using namespace std;

template <typename T>
class Array
{
    T data[100];
    int size;
public:
    Array() : size(0) {}

    void add(const T& element)
    {
        if(size < 100)
        {
            data[size++] = element;
        }
    }

    void remove()
    {
        if(size > 0)
        {
            size--;
        }
    }

    void print()
    {
        for(int i = 0; i < size; i++)
        {
            cout << data[i] << " ";
        }
        cout << endl;
    }
};

int main()
{
    Array<int> arr; // 정수형 배열 생성
    arr.add(10);
    arr.add(20);
    arr.add(30);
    arr.print();

    arr.remove();
    arr.print();
    return 0;
}

// 출력결과:
// 10 20 30
// 10 20

3. 템플릿 특수화

  • 전체 특수화
// 일반 템플릿
template <typename T>
class MyClass
{
public:
    void print()
    {
        cout << "Generic template" << endl;
    }
};

// char* 타입에 대한 특수화
template <>
class MyClass<char*>
{
public:
    void print()
    {
        cout << "Specialized for char*" << endl;
    }
};

int main()
{
    MyClass<int> obj1;
    obj1.print(); // Generic template

    MyClass<char*> obj2;
    obj2.print(); // Specialized for char*

    return 0;
}

특정타입에 대해 다른 동작을 원할때 사용한다.

  • 부분 특수화
// 일반 템플릿
template <typename T1, typename T2>
class Pair
{
public:
    void print()
    {
        cout << "Two different types" << endl;
    }
};

// 두 타입이 같을 때의 부분 특수화
template <typename T>
class Pair<T, T>
{
public:
    void print()
    {
        cout << "Same types" << endl;
    }
};

int main()
{
    Pair<int, double> p1;
    p1.print(); // Two different types

    Pair<int, int> p2;
    p2.print(); // Same types

    return 0;
}

일반 템플릿과 두타입이 같을 때의 부분 특수화로 다르게 동작할때 사용

장점

  • 코드 재사용성 : 하나의 코드로 여러 타입 처리가능
  • 타입 안정성 : 컴파일 타임에 타입 체크
  • 성능 : 런타임 오버헤드 없음
  • 유지보수성 : 중복 코드 감소

단점

  • 컴파일 시간 증가 : 각 타입마다 코드 생성
  • 코드 크기 증가 : 여러 타입에 대한 코드가 생성됨
  • 디버깅 어려움 : 에러 메시지가 복잡할 수 있다.

0개의 댓글