CS/C++

뇌를 자극하는 C++ STL : 4장. 템플릿

샤아이인 2022. 1. 18.

내돈내고 내가 공부한것을 올리며, 중요한 단원은 저 자신도 곱씹어 볼겸 가겹게 포스팅 하겠습니다.

1) 4장. 템플릿

이번시간은 기초 C++문법 복습의 마지막 쳅터이다. 이후 5장부터 이책의 본격적인 주제인 STL에 관하여 다룬다.

 

For_each() 함수 구현해보기

다음 코드는 For_each()를 template함수로 만들어 사용하는 예시이다. 원소의 type을 클라이언트가 직접 결정하여 사용할수가 있다.

#include <iostream>
#include <string>

using namespace std;

template<typename Iter, typename Func>
void For_each(Iter begin, Iter end, Func pf)
{
	while (begin != end)
	{
		pf(*begin++);
	}
}

void PrintInt(int data)
{
	cout << data << " ";
}

void PrintString(string data)
{
	cout << data << " ";
}

int main()
{
	int iarr[5] = { 1, 2, 3, 4, 5 };
	For_each(iarr, iarr + 5, PrintInt);
	cout << endl;

	string sarr[5] = { "zbqmgldjfh", "ZBQMGLDJFH", "World!!" };
	For_each(sarr, sarr + 3, PrintString);

	return 0;
}
 

실행결과는 다음과 같다.

compiler는 클라이언트의 코드를 보고 다음과 같이 template을 instantiation시킨다.

각각 For_each<int*, void(*)(int)>() 와 For_each<string*, void(*)(string)>() 이 된다.

사용시 다음 코드와 같이 명시적으로 작성할수도 있다.

int main()
{
	int iarr[5] = { 1, 2, 3, 4, 5 };
	For_each<int*, void(*)(int)> (iarr, iarr + 5, PrintInt);
	cout << endl;

	string sarr[5] = { "zbqmgldjfh", "ZBQMGLDJFH", "World!!" };
	For_each<string*, void(*)(string)> (sarr, sarr + 3, PrintString);

	return 0;
}
 

더 나아가 PrintInt()와 PrintString() 또한 template화 시켜 사용할수 있다.

#include <iostream>
#include <string>

using namespace std;

template<typename Iter, typename Func>
void For_each(Iter begin, Iter end, Func pf)
{
	while (begin != end)
	{
		pf(*begin++);
	}
}

template<typename T>
void Print(T data)
{
	cout << data << " ";
}

int main()
{
	int iarr[5] = { 1, 2, 3, 4, 5 };
	For_each<int*, void(*)(int)> (iarr, iarr + 5, Print<int>);
	cout << endl;

	string sarr[5] = { "zbqmgldjfh", "ZBQMGLDJFH", "World!!" };
	For_each<string*, void(*)(string)> (sarr, sarr + 3, Print<string>);

	return 0;
}
 

compiler는 템플릿의 매개변수를 유추할수 없으므로 명시적으로 인자의 type을 적어줘야 한다.

 

마지막으로 Print()를 함수 객체 즉, functor로 바꿔보자. 함수객체를 사용시 부가적인 기능을 더하여 제공할 수 있다.

#include <iostream>
#include <string>

using namespace std;

template<typename Iter, typename Func>
void For_each(Iter begin, Iter end, Func pf)
{
	while (begin != end)
	{
		pf(*begin++);
	}
}

template<typename T>
struct PrintFunctor
{
	string sep;

	explicit PrintFunctor(const string& s=" ") : sep(s) {}
	void operator()(T data) const {
		cout << data << sep;
	}
};

int main()
{
	int iarr[5] = { 1, 2, 3, 4, 5 };
	For_each(iarr, iarr + 5, PrintFunctor<int>());
	cout << endl;

	string sarr[5] = { "zbqmgldjfh", "ZBQMGLDJFH", "World!!" };
	For_each(sarr, sarr + 3, PrintFunctor<string>("**"));

	return 0;
}
 

결과는 다음과 같다.

sep이라는 변수에 출력구분 정보를 저장하여 사용하고 있다.

int형에서는 인자를 전달하지 않았기에 dafault값인 공백이 출력되었고, string형에서는 **를 전달하여 구분자로 사용하였다.

결과에서 문자열 사이에 ** 이 삽입된것을 알 수 있다.


2) 나의 현황

갑자기 Python으로 뭘 만들어 봐야겠다는 생각이 들었는데, 문법이 생각이 안난다... 불과 6개월 쯤 전까지만 해도 Python을 많이 사용했는데, 한 6개월 사용 안했더니 잘 기억이 안난다. 혼공파를 다시한번 빠르게 읽어봐야할 것 같다.

이글의 모든 사진과 내용의 출처는 공동환 님께 있습니다.

댓글