본문 바로가기
Script/C++

[C++] Chapter 08. 템플릿(Template) #1

by song.ift 2023. 5. 12.

템플릿 : 함수나 클래스를 찍어내는 툴

  1. 함수 템플릿
  2. 클래스 템플릿

 

함수 템플릿 사용 전

void Print(int a)
{
    cout << a << endl;
}

void Print(float a)
{
    cout << a << endl;
}

void Print(double a)
{
    cout << a << endl;
}

void Print(const char* a)
{
    cout << a << endl;
}

int main()
{
    Print(50);
    Print(50.0f);
    Print(50.0000);
    Print("Hello World");

    return 0;
}

오버라이딩을 통해서 호출할 수 있지만, 불편하다. 큰 틀에서 보면 거의 비슷한 역할을 한다.

그래서 유연하게 바꿔치기 할 수 있는 조커카드를 사용하는게 템플릿.

 

함수 템플릿 사용

template<typename T>     // template<class T> 도 가능.
void Print(T a)
{
    cout << a << endl;
}

template<typename T>
T Add(T a, T b)
{
    return a + b;
}

int main()
{
    Print(50);
    Print(50.0f);
    Print(50.0000);
    Print("Hello World");

    Print<int>(50)  // 명시적으로 지정해줄 수 있음

    int result1 = Add(1, 2);
    float result2 = Add<float>(1.0f, 2.0f);

    return 0;
}

T라는 이름은 다른 값으로 변경 가능하다.

type 자체가 뭔지는 아직 모르지만, 그때그때 가서 정해준다.

 

템플릿은 꼭 하나의 인자만 사용하는 건 아니다

template<typename T1, typename T2>    
void Print(T1 a, T2 b)
{
    cout << a << " " << b << endl;
}

int main()
{
    Print("Hello", 100);

    return 0;
}

 

클래스를 템플릿 함수에 사용하는 경우

class Knight
{
    public:
        int _hp = 100;
}

template<typename T>
void Print(T a)
{
    cout << a << endl;
}

int main()
{
    Knight k1;
    Print(k1);

    return;
}
  • 문제점

cout << a << endl; 실행할 때는 커스텀으로 만들어준 Knight 클래스 같은 경우에 애당초 출력할 때, 오퍼레이터(<< 연산자)를 지원하지 않기 때문에 문제가 된다.

그럴 경우, 연산자 오버로딩을 하면 된다.

class Knight
{
    public:
        int _hp = 100;
}

template<typename T>
void Print(T a)
{
    cout << a << endl;
}

// 연산자 오버로딩 (전역함수 버전)
ostream& operator<<(ostream& os, const Knight& k)
{
    os << k._hp;
    return os;
}

int main()
{
    Knight k1;
    Print(k1);

    return;
}

근데 방금처럼 클래스 같은 경우는 hp값만 덩그러니 출력하는게 그렇고, 특별히 클래스만 특별처리 하고 싶을 때, 템플릿 특수화를 사용할 수 있다.

 

템플릿 함수를 사용하지만, 특정 매개변수에 대해서는 별도처리를 하고 싶은 경우 특수화 개념을 이용한다.

특수화에는 명시적(explicit), 부분(partial) 특수화가 존재한다.

명시적 템플릿 특수화

class Knight
{
    public:
        int _hp = 100;
}

template<typename T>
void Print(T a)
{
    cout << a << endl;
}

// 템플릿 특수화
template<>
void Print(Knight a)
{
    cout << "Knight!!!!" << endl;
    cout << a._hp << endl;	
}

// 연산자 오버로딩 (전역함수 버전)
ostream& operator<<(ostream& os, const Knight& k)
{
    os << k._hp;
    return os;
}

int main()
{
    Knight k1;
    Print(k1);

    return;
}

댓글