C++ Template

이정빈·2023년 6월 1일
0

1. Function Template

템플릿 코드는 컴파일시에 채워진다.
각각 다른 데이터 타입으로 적절하게 컴파일러가 변환시켜준다.

오버로딩과는 다른 점은 한 템플릿을 만들면 여러가지 타입에 맞게 쓸 수 있다는 점이다.
하지만 오류가 자주 일어날 수 있다.
또는 템플릿 적용이 안될때도 있음. 타입이 안맞던가 해서..
그럴 때는 따로 함수를 만들거나 구체화 시키면된다.

template<class T1, class T2>
double add(T1 num1, T2 num2) {
	return num1 + num2;
}

void main() {
	cout << add(2, 3) << endl;
	cout << add(2.1, 2.1) << endl;
	cout << add(1, 1.3) << endl;
}

5
4.2
2.3

저런 식으로 사용하면된다.
사실 저 코드는 리턴 타입 뭐 쓸지 애매하긴하다.

template<class T1, class T2>
double add(T1 num1, T2 num2) {
	return num1 + num2;
}

template<class T>
T add(T num1, T num2) {
	return num1 + num2;
}

void main() {
	cout << add(2, 3) << endl;
	cout << add(2.1, 2.1) << endl;
	cout << add(1, 1.3) << endl;
}

이럴 경우에는 밑에 마지막 식만 맨 위의 템플릿에 들어가게 된다.
컴파일러가 자동으로 적절한 템플릿을 호출해준다.

  1. 전체 특수화
  2. 부분 특수화
  3. 일반 템플릿
    열혈 참고하자

2. Class Template

함수 템플릿과 유사하게 사용된다. 각 데이터 타입마다 클래스가 만들어진다.
데이터 타입 T는 클래스 내부에서 어디든지 사용가능하다.

template<class T>
class Array {
private:
	T* ptr = nullptr;
	int size = 0;
public:
	Array(int size) :size(size) {
		ptr = new T[size];
	}
	int getSize() const {
		return size * sizeof(T);
	}
	~Array() {
		delete[]ptr;
	}
};
void main() {
	Array<int> a1{ 5 };
	cout << a1.getSize() << endl;

	Array<double> a2{ 5 };
	cout << a2.getSize() << endl;
}

20
40

여기서 주의할 점은 클래스내에서 T의 사용하는 방법과 클래스를 호출할 때 타입을 지정해줘야한다는 점이다.

template<class T,int size>로 설정해서 값을 받을 수도 있다. default값도 가능
함수면 인자로 받으면 된당.
template<class T,int size>
class Array {
private:
	T* ptr = nullptr;
public:
	Array(){
		ptr = new T[size];
	}
	int getSize() const {
		return size * sizeof(T);
	}
	~Array() {
		delete[]ptr;
	}
};
void main() {
	Array<int, 5> a1;
	cout << a1.getSize() << endl;
}

3. Specialization

template<class T>
T add(T a, T b) {
	return a + b;
}

template<>
const char* add(const char* a, const char* b) {
	return "char*";
}
void main() {
	cout << add(1, 2) << endl;
	cout << add("a", "b") << endl;
}

3
char*

이렇게 구체화 시켜줘야하는 이유는 단순히 한 템플릿으로 해결되지 않아서이다.
문자열을 합치고 싶다면 strcpy를 써서 하나의 변수를 만들어라

template<class T>
class MyData {
private:
	T data;
public:
	MyData(T value) :data{ value } {}
	T getData() const {
		return data;
	}
};

template<>
class MyData<char*> {
private:
	char* data;
public:
	MyData(const char* value) :data(new char[strlen(value) + 1]) {
		strcpy_s(data, strlen(value) + 1, value);
	}
	const char* getData() const {
		return data;
	}
	~MyData() {
		delete[]data;
	}
};
void main() {
	cout << MyData{ 5 }.getData() << endl;
	cout << MyData<char*>{"dlwlrma"}.getData() << endl;
}

5
dlwlrma

c++17부터 저렇게 식을 쓸 수 있지만 굳이라는 생각이 든다.

Prac 1

int sum;
int intsum;

template<class T>
T* mem(int a) {
	T* tmp = new T[a];
	sum += sizeof(T) * a;
	return tmp;
}

template<>
int* mem(int a) {
	int* tmp = new int[a];
	sum += sizeof(int) * a;
	intsum = sizeof(int) * a;
	return tmp;
}


int main() {
	char* cdata;
	int* idata;
	double* ddata;

	cdata = mem<char>(2);
	idata = mem<int>(2);
	ddata = mem<double>(3);

	cout << "global memeory footprint : " << sum << endl;
	cout << "int memory footprint : " << intsum << endl;

	delete[]cdata;
	delete[]idata;
	delete[]ddata;

	return 0;
}

global memeory footprint : 34
int memory footprint : 8

0개의 댓글