outline
intro to Generic Programming
Function Template
Class Template
STL
templates and inheritance
일반화 프로그래밍(generic Programming)
-
일반화 프로그래밍은 알고리즘에서 매개변수로 제공되는 특정 유형(specific types)에 대해 필요할 때 인스턴스화(instantiated)하는 to-be-specified-later의 관점에서 작성된다.
-
C++에서 template는 서로 다른 타입으로 인해 반복적으로 작성해야 하는 코드를 피하기 위해 사용된다. 즉, 타입에 대해 일반화 접근(Generic Approach)을 한다.
-
함수(functions)와 클래스(class)에서 template를 사용할 수 있다.
template <typename T>
void SelectionSort( T* array, int size) {
for (int i = 0; i < size; ++i) {
int min_idx = i;
for (int j = i + 1; j < size; ++j) {
if (array[min_idx] > array[j]) {
min_idx = j;
}
}
// Swap array[i] and array[min_idx].
T tmp = array[i];
array[i] = array[min_idx];
array[min_idx] = tmp;
}
}
- 만약 위에 예시에 나오는 선택 정렬을 C언어에서 작성을 하였다면 타입만 다른 똑같은 코드를 필요할 때마다 여러 개 작성했어야 했다. 하지만 template로 새로운 변수 T를 통해서 타입에 따라 일반화 코드를 작성할 수 있다.
함수 템플릿(Function Template)
-
함수를 작성할 때, 함수의 기능은 일반화가 되었지만, 자료형(type)에 대해서 모호하게 둔다.
-
동일한 알고리즘의 기능을 다양한 자료형(type)에 대해 한 번 작성한다.
-
특정 자료형(specific type)을 매개 변수(parameter)로 템플릿에 전달
template <typename T>
Swap function
template <typename T>
// naming the arbitrary type T. Programmers use simple names such as T .
void Swap(T &a, T &b) {
T temp;
temp = a;
a = b;
b = temp;
}
- swap 함수를 작성할 때 인자로 받을 매개 변수의 자료형(type)을 template으로 받아서 자료형(type)에 따라 똑같은 swap함수를 만들 필요가 없어진다.
템플릿 인자 추론(Template argument deduction)
- 컴파일러가 해당 템플릿 함수 호출의 사용 및 코드 내용에서 추론할 수 있는 템플릿 인수는 생략할 수 있다.
int i = 10;
int j = 20;
Swap<int>(i, j);
int i = 10;
int j = 20;
Swap(i, j);
- 위에 예시처럼 변수 i와 j가 정수형(int)을 충분히 예상할 수 있기 때문에 Swap 함수에 template 자료형을 사용할 필요가 없다.
함수 템플릿 오버 로딩(Function Template Overloading)
- 함수 템플릿도 동일한 함수 명을 사용하는 것을 허락한다. 다만 오버 로딩의 조건을 따라야 한다. (인자로 받는 변수의 개수를 다르게 하는 것을 추천)
template <typename T>
void Swap(T &a, T &b) {
T temp;
temp = a;
a = b;
b = temp;
}
template <typename T>
void Swap(T* a, T* b, int n) {
T temp;
for (int i = 0; i < n; i++)
{
temp = a[i];
a[i] = b[i];
b[i] = temp;
};
}
클래스 템플릿(class template)
-
클래스 멤버(class member)들도 template로 선언이 가능하다.
-
멤버 함수를 클래스 외부에서 선언할 때, template 선언을 해주어야 한다.
-
클래스 템플릿은 행당 클래스 객체를 생성할 때 template 타입을 선언해준다.
클래스 내부에 사용할 경우(Basic)
template <typename T>
// let the compiler know that you’re about to define a template
class Stack {
private:
enum { MAX = 10 }; // constant specific to class
T items[MAX]; // holds stack items (type-independent)
int top; // index for top stack item
public:
Stack();
};
- 함수 템플릿을 사용했던 것처럼 객체를 생성할 때만 template의 자료형(타입)을 넣어 주면 된다.
클래스 외부에 선언한 멤버 함수를 사용할 경우
template <typename T>
class MyPair {
T a, b;
public:
MyPair(T first, T second) {
a = first, b = second;
}
T get_max();
};
template <typename T>
T MyPair<T>::get_max() {
T retval;
retval = a > b? a : b;
return retval;
}
int main() {
int a_i = 100, b_i = 75;
MyPair<int> my_pair_i(a_i, b_i);
cout << "max(" << a_i << "," << b_i << ")=" << my_pair_i.get_max() << endl;
double a_d = 1.5, b_d = -3.5;
MyPair<double> my_pair_d(a_d, b_d);
cout << "max(" << a_d << "," << b_d << ")=" << my_pair_d.get_max() << endl;
return 0;
}
- 멤버 함수를 사용할 때(위에 예시에서는 MyPair 함수를 사용할 때)마다 template의 자료형(타입)을 넣어준다.
멤버 함수에 있는 템플릿(Member Function Template)을 사용할 경우
-
클래스 템플릿(Class template)의 매개 변수 이외의 부가적으로 템플릿 매개 변수를 제공하는 데 사용할 수 있음
-
부가적으로 클래스 멤버 안에 템플릿을 사용할 경우 외부에 부가적으로 사용한 멤버 템플릿도 선언해줘야 한다.
template<typename T>
class X {
public:
template<typename U>
void mf(const U& u);
};
template<typename T>
template<typename U>
void X<T>::mf(const U& u) {
...
}
int main() {
...
}
typename & class keyword
-
typename 은 'class'로 항상 대체될 수 있다.
template <class First, class Second>
struct Pair {
First first;
Second second;
Pair(const First& f, const Second& s) : first(f), second(s) {}
};
template <class First, class Second>
Pair<First, Second> MakePair(const First& first,const Second& second) {
return Pair<First, Second>(first, second);
}
int main (){
Pair<int, int> p = MakePair(10, 10);
// == MakePair<int, int>(10, 10);
Pair<int, int> q = Pair<int, int>(20, 20);
return 0;
}
비형식 템플릿 변수(Non-type Template Parameter)
-
c++ 템플릿에서는 비형식 매개 변수를 지원한다. ( 상수 정수 계열 값을 제공하여 배열의 길이를 지정할 수 있다.)
-
변수는 constant로 표현되어야 한다.
-
const드로 취급되어야 한다.
template<class T, int size>
template<class T, int size>
class MyFilebuf {
T* filepos;
int array[size];
public:
MyFilebuf() { /* ... */ }
~MyFilebuf() {}
...
};
int main (){
MyFilebuf<double, 200> x; // create object x of class
MyFilebuf<double, 200.0> y;
// error, 200.0 is a double, not an int
return 0;
}
template <int i>
class C {
public:
int array[i];
int k;
C() { k = i; }
};
int main() {
C<100> a; // can be instantiated
C<200> b; // can be instantiated
return 0;
}
표준 템플릿 라이브러리-STL(Standard Template Library)
- STL은 템플릿(template)으로 작성된 제네릭 클래스와 함수 라이브러리이다.
1.순차(Sequence) : 연속적인 메모리 공간에 순차적으로 값을 저장하고 있는 컨테이너이다.
-
벡터(Vectors) : 입력된 순서대로 저장
-
리스트(List) : 순서가 있는 리스트 형태
-
디큐(Deque - double-ended queue) : 양 끝단에서 입력과 출력이 가능
2.컨테이너 어댑터(Container adapter)
-
스택(Stack) : 선입 후출(Last In Last Out)
-
큐(Queue) : 선입선출(Frist In First Out)
3.연관 컨테이너(Associative Container : a generalization of sequence)
-
Set : key만을 저장하는 자료구조로 중복되지 않은 key를 저장한다. set에 값을 한번 넣어보는 것으로 중복된 값을 찾을 수 있다.
-
Map : key와 value 정보를 가지고 있는 자료구조이다.
-
Multimaps : key로 인덱싱 되는 여러 개의 다른 원소를 허용한다.
템플릿과 상속(Templates and Inheritance)
-
일반 클래스가 파생 클래스인 경우 템플릿 클래스를 상속 가능하며, 템플릿 클래스가 파생 클래스인 경우에도 템플릿 클래스를 상속 가능하다.
template<class T>
class Base {
public:
void set(const T& val) { data = val; }
private:
T data;
};
template<class T>
class Derived : public Base<T> {
// should be Base<T>, not just Base
public:
void set(const T& val);
};
template<class T>
void Derived<T>::set(const T& v) {
Base<T>::set(v);
// should be Base<T>, not just Base
}
'Language > C++' 카테고리의 다른 글
[C++] 예외 처리(Exception Handling) - 컴도리돌이 (0) | 2021.01.01 |
---|---|
[C++] 복사 생성자, 연산자 오버로딩(Copy Constructor, Operator Overloading)- 컴도리돌이 (0) | 2020.12.31 |
[C++] 다형성(Polymorphism)-(1) - 컴도리돌이 (0) | 2020.12.28 |
[C++] 상속(Inheritance) - 컴도리돌이 (0) | 2020.12.27 |
[C++] 이중 연결 리스트 (Double Linked List) - 컴도리돌이 (0) | 2020.10.28 |