1. 템플릿이란?

템플릿(Template)은 제네릭 프로그래밍을 구현하기 위한 C++의 강력한 기능입니다.

핵심 개념

  1. 유연한 코드 작성:
    • 템플릿은 특정 데이터 타입에 의존하지 않고 코드 작성이 가능하게 합니다.
    • 다양한 데이터 타입에 대해 코드 재사용성을 극대화할 수 있습니다.
  2. 컴파일 시점 처리:
    • 템플릿은 런타임이 아닌 컴파일 시점에 모든 것이 결정됩니다.
    • 사용되지 않는 템플릿 코드는 컴파일되지 않으므로 불필요한 코드가 생성되지 않습니다.
  3. C++의 특징:
    • C++의 템플릿은 C#의 제네릭(Generic)과 유사하지만, 더 많은 기능과 복잡한 문법을 제공합니다.

템플릿 종류

  1. 함수 템플릿:
    • 함수의 데이터 타입을 일반화합니다.
    • 동일한 로직을 다양한 데이터 타입에 대해 적용할 수 있습니다.
  2. 클래스 템플릿:
    • 클래스 멤버 변수와 함수의 데이터 타입을 일반화합니다.
    • 다양한 데이터 타입에 대해 동일한 클래스를 사용할 수 있습니다.

2. 함수 템플릿

2.1 기본 함수 템플릿

template<typename T>
void Print(T a)
{
    std::cout << a << std::endl;
}
  • 구조:

    • template<typename T>: 템플릿 선언 부분입니다.
      • T는 타입 파라미터로, 호출 시점에서 데이터 타입이 결정됩니다.
      • typename 대신 class 키워드도 사용할 수 있습니다.
    • Print 함수는 데이터 타입에 의존하지 않고 호출된 데이터 타입에 따라 동작합니다.
  • 사용 예시:

    Print<int>(10);        // 명시적으로 <int> 타입 지정
    Print(3.14);           // 컴파일러가 <double>로 타입 추론
    Print("Hello World");  // <const char*> 타입으로 추론

2.2 다중 타입 템플릿

template<typename T1, typename T2>
void Print(T1 a, T2 b)
{
    std::cout << a << " " << b << std::endl;
}
  • 구조:

    • T1T2라는 두 개의 타입 파라미터를 사용하여 서로 다른 데이터 타입을 처리합니다.
    • 여러 데이터 타입의 입력을 처리하는 데 유용합니다.
  • 사용 예시:

    Print(10, "Hello");        // T1 = int, T2 = const char*
    Print(3.14, 42);           // T1 = double, T2 = int

2.3 함수 템플릿의 특수화

template<>
void Print<int>(int a)
{
    std::cout << "특수화된 정수 출력: " << a << std::endl;
}
  • 설명:

    • 템플릿의 특수화(Specialization)는 특정 데이터 타입에 대해 템플릿의 동작을 다르게 정의하는 기능입니다.
    • 위 코드에서 int 타입에 대해서는 "특수화된 정수 출력"이라는 고유 메시지가 출력됩니다.
  • 사용 예시:

    Print(10);        // "특수화된 정수 출력: 10"
    Print(3.14);      // 일반 템플릿 호출

2.4 함수 템플릿의 장점

  • 동일한 로직을 다양한 데이터 타입에 대해 재사용 가능.
  • 코드 중복 제거.
  • 컴파일러가 타입을 자동으로 추론하므로 호출이 간편함.

3. 클래스 템플릿

3.1 기본 클래스 템플릿

template<typename T>
class Stack
{
private:
    T elements[100];   // 데이터 타입 T로 구성된 배열
    int top;
public:
    void push(T element)
    {
        elements[top++] = element;
    }
    T pop()
    {
        return elements[--top];
    }
};
  • 구조:

    • template<typename T>: 클래스 템플릿 선언.
    • T는 멤버 변수와 멤버 함수의 데이터 타입을 일반화합니다.
    • push 함수와 pop 함수는 T 타입의 데이터를 처리합니다.
  • 사용 예시:

    Stack<int> intStack;       // 정수형 스택
    intStack.push(10);
    std::cout << intStack.pop() << std::endl;  // 출력: 10
    
    Stack<std::string> strStack; // 문자열형 스택
    strStack.push("Hello");
    std::cout << strStack.pop() << std::endl; // 출력: Hello

3.2 다중 타입 클래스 템플릿

template<typename T1, typename T2>
class Pair
{
private:
    T1 first;
    T2 second;
public:
    Pair(T1 a, T2 b) : first(a), second(b) {}
    void Print()
    {
        std::cout << first << ", " << second << std::endl;
    }
};
  • 구조:

    • T1T2라는 두 개의 타입 파라미터를 사용하여 두 가지 다른 데이터 타입을 처리합니다.
    • Pair 클래스는 두 개의 데이터를 저장하고 출력하는 역할을 합니다.
  • 사용 예시:

    Pair<int, std::string> p1(1, "Apple");
    p1.Print();   // 출력: 1, Apple

3.3 클래스 템플릿의 특수화

template<>
class Stack<bool>
{
private:
    unsigned char bitArray[100]; // 비트를 사용하여 bool 값을 압축 저장
    int top;
public:
    void push(bool value)
    {
        // 특수화된 push 구현
    }
    bool pop()
    {
        // 특수화된 pop 구현
    }
};
  • 설명:
    • bool 타입에 대해 클래스 템플릿을 특수화하여 메모리를 최적화한 구현을 제공합니다.
    • bool 값은 각 비트로 저장되므로 메모리 사용량을 대폭 줄일 수 있습니다.

4. 템플릿 문법 심화

4.1 기본값 제공

template<typename T = int>
class RandomBox
{
private:
    T data[100];
public:
    T GetRandomData()
    {
        int index = rand() % 100;
        return data[index];
    }
};
  • 설명:

    • T = int: 타입 파라미터 T의 기본값을 int로 설정.
    • 만약 사용자가 T를 지정하지 않으면 int로 간주됩니다.
  • 사용 예시:

    RandomBox<> rb;  // T가 int로 설정
    RandomBox<float> rbFloat;  // T를 float로 설정

4.2 템플릿 함수와 일반 함수의 동작 차이

void Print(int a)
{
    std::cout << "일반 함수: " << a << std::endl;
}

template<typename T>
void Print(T a)
{
    std::cout << "템플릿 함수: " << a << std::endl;
}
  • 사용 예시:

    Print(10);  // 일반 함수 호출
    Print(3.14);  // 템플릿 함수 호출
  • 설명:

    • 템플릿 함수보다 일반 함수가 우선적으로 호출됩니다.
    • 이는 템플릿이 일반 함수의 대체물이 아닌 보조 역할을 한다는 것을 의미합니다.

5. 템플릿 사용 시 주의점

  1. 헤더 파일에서 정의:

    • 템플릿은 헤더 파일에서 정의와 구현이 모두 이루어져야 합니다.
    • 이는 템플릿이 컴파일 시점에 타입을 추론하기 때문입니다.
  2. 컴파일 오류:

    • 템플릿 코드는 인스턴스화될 때 타입이 결정되므로, 사용하지 않는 템플릿 코드는 컴파일되지 않습니다.
  3. 템플릿 특수화의 활용:

    • 특수화는 효율성과 가독성을 위해 사용됩니다.
    • 하지만 과도한 특수화는 코드의 복잡성을 증가시킬 수 있습니다.

6. 템플릿의 장점과 단점

장점

  • 코드 재사용성 증가:
    • 여러 데이터 타입에 대해 동일한 로직을 작성 가능.
  • 유연성:
    • 데이터 타입에 구애받지 않는 범용 코드를 작성 가능.

단점

  • 복잡성:
    • 문법이 어렵고 코드 가독성이 떨어질 수 있음.
  • 컴파일 시간 증가:
    • 컴파일러가 모든 템플릿 인스턴스를 생성해야 하므로 컴파일 시간이 길어질 수 있음.

profile
李家네_공부방

0개의 댓글