프로그래밍 공부
작성일
2023. 5. 31. 22:27
작성자
WDmil
728x90

Template는 class의 일반화 프로그래밍을 이야기한다.

 

어떠한 객체에 대한 반환형 또는 매개변수의 입력형을 일반화 시켜, 동일한 코드에 대해 다양한 데이터 유형을 하나의 함수로 재사용하고, 유형 안정성을 유지하기 위해 사용한다.

 

이러한 템플릿은, 크게 함수 템플릿 과 클래스 템플릿 으로 나눌 수 있다.

  • 함수 템플릿 (Function Template)
    • 일반적인 함수 틀을 제공하고, 특정한 데이터 유형에 대해 작동하는 실제 함수를 생성한다.
    • 함수 매개변수나 매개변수의 반환유형에 사용한다.
  • 클래스 템플릿 (Class Template)
    • 일반적인 클래스 틀을 제공하며, 대부분의 데이터 유형에 대해 작동하는 클레스를 생성한다.
    • 멤버변수, 멤버 함수에 반환유형이나, 매개변수에 사용한다.

Function_Template

#include <iostream>

using namespace std;
// 일반화 프로그래밍, 다양한 프로그램에 동일한 알고리즘을 넣어야 할 때 사용한다.

//int GetMax(int x, int y) { return x > y ? x : y; }
//short GetMax(short x, short y) { return x > y ? x : y; }
//double GetMax(double x, double y) { return x > y ? x : y; }
//float GetMax(float x, float y) { return x > y ? x : y; }

// 템플릿 선언시 다음과 같이 선언해주면 된다.
template <typename T>
T GetMax(T x, T y) { return x > y ? x : y; }

class Won
{
	int value = 0;
public:
	Won(int value = 0) : value(value) {}

	bool operator > (const Won& rhs)
	{
		return value > rhs.value;
	}

	friend ostream& operator << (ostream& out, const Won& won)
	{
		cout << won.value;
		return out;
	}
};

int main()
{
	cout << GetMax(1, 2) << endl;
	cout << GetMax(1.1f, 2.0f) << endl;
	cout << GetMax(1.2, 2.3) << endl;
	cout << GetMax(1u, 2u) << endl;
	cout << GetMax(1ll, 2ll) << endl;

	// cout << GetMax(1, 2.0f) << endl; 이경우에는 오류가 난다. T가 같은 Type 이기 때문에.

	cout << GetMax<int>(1, 2.0f) << endl;

	cout << GetMax(Won(6), Won(2)) << endl;
	return 0;
}

위와 같이 template 로 대부분의 유형에 대처할 수 있다.

#pragma once
#include <iostream>

using namespace std;

template <class T>
class myArray
{
public:
	myArray(int length)
		: length(length)
	{
		arr = new T[length];
	}
	~myArray()
	{
		delete[] arr;
	}
	void Print();

private:
	T* arr = nullptr;
	int length = 0;
};

template<class T>
inline void myArray<T>::Print()
{
	std::cout << "Hello" << std::endl;
}

int main()
{
	myArray<int> myArr(10);

	myArr.Print();

	return 0;
}
// 컴파일 타이밍에 인라인화 시켜준다. 사용시점에 이미 구현도가 정의되어있어야한다.
// 그러나, 그러한 구현부가 class T 가 분리되어 있어서 컴파일러가 받아들이지 못한다.


// 템플릿 자체가 함수를 정의하기 위해 만든 틀. 함수 자체가 정의된 상태가 아니다.
// 템플릿 코드 자체가 컴파일 시에 정의가 된다.

// 컴파일러가 인라인화 시키면서 함수가 최적화 되어있는지, 아닌지 확인해서 그대로 코드영역에 넣을지 검사한다.
// 컴파일 타임에 만들어 진다는 뜻 은 사용 시점에 모든것이 정의되어 있어야 한다는 것.
// 그러나, class T 는 만들어져 있지 않기 때문에, 컴파일러가 넣을지 바꿀지 확인해야 하는데, 컴파일러는 헤더를 같이 읽지 못하고 따로 읽는다.
// 정의되어있지 않은 class T에 대한 함수를 컴파일러는 읽지 못하기 때문에, 따로 분리되어 있는 함수를 확인하지 못한다.

 

이러한 함수를 분리하여 파일별로 분류할 수 있는데, 컴파일러가 인식하지 못하는 문제가 발생할 수 있다.

그렇게되면, 링크에러가 나타나게 되는데

 

이러한 링크 에러는 컴파일 방식에 의해 어쩔 수 없이 발생한다.

 

 

일반적으로. 컴파일러가 헤더와 소스로 나뉘어진 파일을 컴파일 할 때 에는 다음과 같은 순서로 이루어 진다.

 

헤더 호출 >> 링크 >> 소스 호출, 연결 >> 코드영역 전송

그러나, template는 설계상 위와같은 순서를 따르지 않고. 다음과 같은 순서로 컴파일러가 이용하게 된다. 

헤더 호출 >> template >> 코드영역 전송

template 는, 설계 상. 특정 데이터 유형에 대해 코드를 생성하기 위해서 컴파일 시점에서 필요한 정보를 사용하게 되는데.

이 시점이 링크 이후 가 아닌 링크 이전 타이밍에 이용하게 되고, 템플릿 자체의 정의는 소스파일이 개별적으로 컴파일 되지 않고. 헤더에 존재하는 인스턴스화에 필요한 정보를 포함하는 오브젝트 파일이 생성되지 않아서. 링크 에러가 발생하게 된다.

 

즉, template를 사용하기 위해서는 어떠한 객체의 매개함수를 그 객체의 위에서 미리 정의해줄 필요가 있고.

#include "객체의.cpp" 를 미리 해주어야 할 필요가 있다는것 이다.

728x90