프로그래밍 공부
작성일
2023. 6. 2. 01:13
작성자
WDmil
728x90

C++에서 template를 사용하는 방법 중, 자료 형 이 아닌 매개변수를 template로 사용하는 방법이 있다.

#include <iostream>

using namespace std;
// 자료형이 아닌 매개변수를 받아오는 템플릿

template<typename T, unsigned int SIZE>
class MyArray
{
public:
	MyArray() = default;
	~MyArray() {}

	T& operator[](int index) {
		return arr2[index];
	}
private:
	T arr1[10]; // 상수만 들어가면서 형태만 띄고있는것.
	T arr2[SIZE];
};

int main()
{
	MyArray<int, 30> arr1;
	MyArray<float, 30u> arr2;

	for (int i = 0; i < 30; i++)
		arr1[i] = i;

	for (int i = 0; i < 30; i++)
		arr2[i] = i;

	for (int i = 0; i < 30; i++)
		cout << arr1[i] << ' ';
	std::cout << std::endl;

	for (int i = 0; i < 30; i++)
		cout << arr2[i] << ' ';
	std::cout << std::endl;

	return 0;
}

template 특수화

특정 자료형에 대해 virtual 처리 또는 함수 오버로딩 처리 하여 특정상황 에서만 동작하게 하는것.

#include <iostream>

using namespace std;

// 템플릿 특수화
// 템플릿은 어떠한 자료형이 들어가든 동작하도록 넣는건데,
// 특정한 자료형에 대해 예외처리를 하기 위해 만들어지는 것.

template<typename T>
T GetMax(T x, T y)
{
	return (x > y) ? x : y;
}

template<>
char GetMax(char x, char y)
{
	cout << "Warning : comparing chars" << endl;
	return (x > y) ? x : y;
}

template<class T>
class Storage
{
	T value;
public:
	Storage(T value)
		:value(value)
	{}

	void Print()
	{
		cout << value << endl;
	}
};

 // 이와 같은 경우로 template 또한 다형성의 형태 중 하나임 을 알 수 있다.
template <>
void Storage<double>::Print()
{
	cout << "double : " << value << endl;
}

int main()
{
	cout << GetMax<int>(1, 2) << endl;
	cout << GetMax<float>(1.1f, 2.2f) << endl;
	cout << GetMax<char>(1, 2) << endl;
	cout << GetMax('a', 'b') << endl;

	Storage<int> s1(5);
	s1.Print();

	Storage<double> s2(5.5);
	s2.Print();

	return 0;
}

Class Template

함수 클래스 자체 전체를 특수화 하여, 탬플릿으로 만드는것.

#include<iostream>

using namespace std;
// 클래스 자체, 전체의 특수화 이다.

template<class T>
class A
{
public:
	A(const T& input) {}
	void DoSomthing()
	{
		cout << typeid(T).name() << endl;
	}

	void Test() {}
};

// class 자체를 특수화 하였을 때. 매개함수를 바꾸어줄 수 있다.
template<>
class A<char>
{
public:
	A(const char& input) {}
	void DoSomthing()
	{
		cout << "char type specialization" << endl;
	}
};

int main()
{
	A<int> aint(10);
	A<double> adouble(10.1);
	A<char> achar('a');

	aint.DoSomthing();
	adouble.DoSomthing();
	achar.DoSomthing();

	aint.Test();
	adouble.Test();
	//achar.Test(); achar에는 Test 인수가 없다.


	return 0;
}

일반 함수, 클래스 맴버함수 특수화

#include<iostream>

using namespace std;
// 부분만 특수화 시키고 싶을 때 사용한다.
// 함수에 대한 부분 특수화를 진행한다.
#pragma region 1.일반 함수 부분 특수화
//template<class T, int size>
//class StaticArray
//{
//	T arr[size];
//
//public:
//	T* GetArray() { return arr; }
//
//	T& operator[](int index)
//	{
//		return arr[index];
//	}
//
//	void Print1()
//	{
//		for (int i = 0; i < size; i++)
//		{
//			cout << (*this)[i] << ' ';
//		}
//		cout << endl;
//	}
//};
//
//template<typename T, int size>
//void Print2(StaticArray<T, size>& arr)
//{
//	for (int i = 0; i < size; i++)
//	{
//		cout << arr[i] << ' ';
//	}
//	cout << endl;
//}
//
//template<int size>
//void Print2(StaticArray<char, size>& arr)
//{
//	for (int i = 0; i < size; i++)
//	{
//		cout << arr[i];
//	}
//	cout << endl;
//}
#pragma endregion
#pragma region 2.클래스 멤버 함수 부분 특수화
template<class T, int size>
class StaticArray_Base
{
	T arr[size];

public:
	T* GetArray() { return arr; }

	T& operator[](int index)
	{
		return arr[index];
	}

	virtual void Print1()
	{
		for (int i = 0; i < size; i++)
		{
			cout << (*this)[i] << ' ';
		}
		cout << endl;
	}
};

template<class T, int size>
class StaticArray : public StaticArray_Base<T, size>
{

};

template<int size>
class StaticArray<char, size> : public StaticArray_Base<char, size>
{
public:
	void Print1() override
	{
		for (int i = 0; i < size; i++)
		{
			cout << (*this)[i];
		}
		cout << endl;
	}
};
#pragma endregion
int main()
{
	StaticArray<int, 4> int4;
	int4[0] = 1;
	int4[1] = 2;
	int4[2] = 3;
	int4[3] = 4;

	int4.Print1();
	//Print2(int4);

	StaticArray<char, 6> char6;
	char6[0] = 'H';
	char6[1] = 'E';
	char6[2] = 'L';
	char6[3] = 'L';
	char6[4] = 'O';
	char6[5] = '\n';

	char6.Print1();
	//Print2(char6);

	return 0;
}

Class 포인터 에 대한 특수화

#include <iostream>

using namespace std;

template<class T>
class A
{
	T value;
public:
	A(const T& value) : value(value) {}
	void Print()
	{
		cout << value << endl;
	}
};

template<class T>
class A<T*>
{
	T* value;
public:
	A(T* value) : value(value) {}
	void Print()
	{
		cout << *value << endl;
	}
};

int main()
{
	A<int> Aint(123);
	Aint.Print();

	int temp = 456;
	A<int*> Aptr(&temp);
	Aptr.Print();
	return 0;
}
728x90