본문 바로가기
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; }

댓글