템플릿(template)
C++에서 언어 차원에서 객체지향 프로그래밍 뿐만 아니라 제네릭 프로그래밍(generic programming)도 지원한다.
제네릭 프로그래밍은 데이터를 중요시하는 객체지향적 프로그래밍 철학보단 알고리즘에 그 중점을 두었다.템플릿(template)은 데이터 타입(data type)이 아닌
매개변수의 타입에 따라 클래스를 생성하는 클래스 템플릿 과 메서드 템플릿, C++14 이후 부터는 변수 템플릿 이 있다.또한 템플릿은 템플릿 특수화라 하여 범위에 따라 다르게 템플릿을 적용시키는 템플릿 특수화 라는 개념이 있다.
- 함수 템플릿 특수화
- 클래스 템프릿 특수화
- 포인터에 대한 특수화
템플릿에 의한 형변환은 컴파일 타임에 결정된다. 즉 사람이 타입을 맞춰줄 필요없이 컴파일러에게 타입 결정하기를 시킨다.
아래 예에서 각각의 템플릿을 보고 이해 하자.
함수 템플릿
템플릿을 적용시키지 않은 코드
//템플릿을 적용시키지 않은 코드의 예
int getMax(int a, int b)
{
return (a > b) ? a : b;
}
char getMax(char a, char b)
{
return (a > b) ? a : b;
}
double getMax(double a, double b)
{
return (a > b) ? a : b;
}
int main(void)
{
cout << getMax(2, 3) << '\n';
cout << getMax(3.14, 1.592) << '\n';
cout << getMax('a', 'c') << '\n';
return 0;
}
템플릿을 적용시킨 코드
template<typename T>
T getMax(T x, T y)
{
return (x > y) ? x : y;
}
int main(void)
{
cout << getMax(2, 3) << '\n';
cout << getMax(3.14, 1.592) << '\n';
cout << getMax<char>('a', 'c') << '\n';
return 0;
}
템플릿을 적용 시킨 코드를 보면 알 수 있듯 template <typename T> 을 지정하여
함수 내 반환 및 매개변수 타입을 T로 받아 컴파일러에게 형변환을 시킬 수 있다.
또한 코드 라인을 보면 반복되는 부분의 재사용성을 증가시켜주는 것을 알 수 있다.
클래스 템플릿
위의 템플릿 타입변수 T를 사용하여 클래스에 적용시켜 보자.
Myarray.h 파일
template<typename T>
class MyArray
{
private :
int m_length;
T* m_data;
public :
MyArray()
{
m_length = 0;
m_data = nullptr;
}
MyArray(int length)
{
m_length = length;
m_data = new T[length];
}
~MyArray()
{
delete[] m_data;
m_data = nullptr;
}
/* [] 연산자를 재정의 하여 값의 범위를 검사해주고,
** 배열내 인덱스에 위치한 값을 반환해준다.
** 반환 타입은 T&로 기본 데이터 타입에 상관없이
** int, char, double 같은것이 와도 반환 할 수 있다.
*/
T& operator[](int index)
{
assert(index >= 0 && index < m_length);
return m_data[index];
}
int getLength() { return m_length; }
// 해당 객체내 데이터(m_data)배열의 원소들을 출력한다.
void print()
{
using namespace std;
for (int i = 0; i < m_length; ++i)
cout << m_data[i] << ' ';
cout << '\n';
}
};
MyArray.cpp 파일 (main문)
#include "MyArray.h"
int main()
{
// char형 배열을 생성.
MyArray<char> my_arr(10);
//a(아스키 65)부터 10개를 대입 및 출력(print())
for (int i = 0; i < my_arr.getLength(); ++i)
my_arr[i] = i + 65;
my_arr.print();
// int형 배열을 생성
MyArray<int> my_IntegerArr(10);
//1~10까지 대입 및 출력(print())
for (int i = 0; i < my_IntegerArr.getLength(); ++i)
my_IntegerArr[i] = i + 1;
my_IntegerArr.print();
return 0;
}
auto와 template의 차이점
C++14부터는 auto를 함수의 return 타입과 람다의 인자에서도 사용이 가능한데 이 때는 braced initializer를 std::initializer_list형으로 인식하지 못한다.
즉 아래 두 가지 경우에 대해서는 (auto 타입 추론이 아닌) 템플릿 타입 추론 을 한다.
// auto 타입 추론
auto arr = { 1, 2, 3 }; // arr 타입은 std::initializer_list형으로 추론됨
// template 타입 추론
template
void f(T arr);
f({ 1, 2, 3 }); // Error. 이니셜라이저 리스트 타입 추론이 안된다.
auto는 또한 C++14에서 return 값으로 {1,2,3} 타입 추론이 안된다.
auto func()
{
return {1,2,3}; // Error.
}
'Programing_Language > C++' 카테고리의 다른 글
assert (단언하기) in C++ (0) | 2020.12.15 |
---|---|
템플릿(Template) (2/2) (템플릿 특수화) (0) | 2020.12.14 |
2차원 동적 배열 할당과 해제 (배열 vs 벡터) (0) | 2020.12.07 |
enum과 enum class (열거 타입과 엄격한 열거 타입) (0) | 2020.12.06 |
VisualStudio 내부 스택 크기 조절방법 (0) | 2019.04.06 |
댓글