3 minute read

1. 템플릿 이해하기

  • 모형자 : 모양을 그릴 때 쓰는 것
  • 함수 템플릿 : 함수를 만드는 도구. 함수의 기능은 결정되어 있지만, 자료형은 결정되어 있지 않아서 결정해야한다.
template <typename T>   //아래 함수를 템플릿으로 정의한다는 의미
//template <class T> 라고 해도 된다
T Add(T num1, T num2){
    return num1 + num2;
}
  • 자료형을 결정짓지 않았다. 나중에 T를 대신하여 실제 자료형을 결정한다
  • 위 템플릿으로 아래와 같이 사용할 수 있다
    template<typename T>
    T Add(T num1, T num2){
        return num1 + num2;
    }

    int main(void){
        cout << Add<int>(15,20) << endl;
        cout << Add<double>(1.5, 2.3) << endl;
        cout << Add<int>(20,20) << endl;
        return 0;
    }
  • 자료형을 적용한 함수를 컴파일러가 한번 정의하게 되면 그 다음에는 새로 함수를 만들지 않고 앞서 만들어 놓은 함수를 다시 호출한다.
```cpp
template<typename T>
T Add(T num1, T num2){
    return num1 + num2;
}

int main(void){
    cout << Add(15,20) << endl;
    cout << Add(1.5, 2.3) << endl;
    cout << Add(20,20) << endl;
    return 0;
}
```     + 이렇게 해도 컴파일러가 알아서 결정해준다

✏️함수 템플릿, 템플릿 함수

  • 함수 템플릿
    template<typename T>
     T Add(T num1, T num2){
         return num1 + num2;
     }
    
  • 템플릿 함수 : 템플릿 기반으로 컴파일러가 만들어낸 함수
     int Add<int>(int num1, int num2){
         return num1 + num2;
     }
    

✏️둘 이상의 형에 대한 템플릿

  • 이런 것도 됨
template <class T1, class T2>       //typename대신 class 사용
void ShowData(double num){
    cout << (T1)num << ", " << (T2)num << endl;
    //형 변환문 -> (int)67.2 : 67.2를 정수형으로 변환
}

int main(void){
    ShowData<char, int>(65);
    ShowData<char, int>(67);
    ShowData<char, double>(68.9);
    ShowData<short, double>(67.2);
    ShowData<short, double>(69.4);
    return 0;
}

/*실행결과
A, 65
C, 67
D, 68.9
67, 67.2
69, 69.4
*/

✏️함수 템플릿의 특수화

```cpp
#include <iostream>
using namespace std;

template <typename T>
T Max(T a, T b) 
{
    return a > b ? a : b ; 
}

int main(void)
{
    cout<< Max(11, 15)				<<endl;
    cout<< Max('T', 'Q')			<<endl;
    cout<< Max(3.5, 7.5)			<<endl;
    cout<< Max("Simple", "Best")	<<endl;
    return 0;
}
```  

위의 함수 템플릿은 인자로 전달된 두 데이터 중 더 큰 값을 반환하는데, 문자열의 경우 단순히 주소값이 비교되는 것이라 아무런 의미가 없다. 
길이비교가 목적이라면 `strlen`을 써주거나, 사전순이 목적이라면 `strcmp`로 구성하는 것이 의미가 있다   

상황에 따라서 템플릿 함수 구성 방법에 예외를 둘 필요가 있는데 이것이 함수 템플릿의 특수화이다.

#include <iostream>
#include <cstring>
using namespace std;

template <typename T>
T Max(T a, T b) 
{
	return a > b ? a : b ; 
}

template <>         //char* 형은 개발자가 제시하고 있으므로, 컴파일러는 함수를 별도로 만들지 않고 이 함수를 호출한다
char* Max(char* a, char* b)
{
	cout<<"char* Max<char*>(char* a, char* b)"<<endl;
	return strlen(a) > strlen(b) ? a : b ;
}

template <> 
const char* Max(const char* a, const char* b)
{
	cout<<"const char* Max<const char*>(const char* a, const char* b)"<<endl;
	return strcmp(a, b) > 0 ? a : b ;
}


int main(void)
{	cout<< Max(11, 15)				<<endl;
	cout<< Max('T', 'Q')			<<endl;
	cout<< Max(3.5, 7.5)			<<endl;
	cout<< Max("Simple", "Best")	<<endl;

	char str1[]="Simple";
	char str2[]="Best";
	cout<< Max(str1, str2)			<<endl;
	return 0;
}

2. 클래스 템플릿

  • 필요한 이유
    • 제공되는 기능과 내부 행동이 동일하지만, 저장의 대상이 다르다는 이유만으로 유사한 클래스를 여러개 정의하는 것은 비효율적이기 때문
  • 클래스 템플릿 정의
    • 함수 템플릿과 동일하다
      #include <iostream>
      using namespace std;
      
      template <typename T>
      class Point 
      {
      private:
      	T xpos, ypos;
      public:
      	Point(T x=0, T y=0) : xpos(x), ypos(y)
      	{  }
      	void ShowPosition() const
      	{
      		cout<<'['<<xpos<<", "<<ypos<<']'<<endl; 
      	}
      };
      
      int main(void)
      {
      	Point<int> pos1(3, 4);
      	pos1.ShowPosition();    
      
          Point<double> pos2(2.4, 3.6);
      	pos2.ShowPosition();
      
      	Point<char> pos3('P', 'F');    // 좌표정보를 문자로 표시하는 상황의 표현
      	pos3.ShowPosition();
      	return 0;
      }
      
    • 템플릿 함수와는 다르게 자료형을 꼭 명시해주어야 한다.

✏️클래스 템플릿 선언과 정의 분리

#include <iostream>
using namespace std;

template <typename T>
class Point 
{
private:
	T xpos, ypos;
public:
	Point(T x=0, T y=0);
	void ShowPosition() const;
};

template <typename T>
Point<T>::Point(T x, T y) : xpos(x), ypos(y)
{  }

template <typename T>
void Point<T>::ShowPosition() const
{
	cout<<'['<<xpos<<", "<<ypos<<']'<<endl; 
}


int main(void)
{
	Point<int> pos1(3, 4);
	pos1.ShowPosition();

	Point<double> pos2(2.4, 3.6);
	pos2.ShowPosition();

	Point<char> pos3('P', 'F');    // 좌표정보를 문자로 표시하는 상황의 표현
	pos3.ShowPosition();
	return 0;
}

❗중요한것은 헤더파일과 cpp파일, main파일을 나눌 때,
1) 클래스 템플릿의 정의는 헤더파일에 모두 넣거나
2) main에 헤더파일과 cpp파일을 모두 include 시켜주어야한다.

  • 컴파일러는 파일단위로 컴파일하기 때문에 서로 다른 파일의 내용을 참조하지 않는다.

Tags: ,

Categories:

Updated: