- [C++] template2022년 08월 14일
- starryeye
- 작성자
- 2022.08.14.:56
다 아는 내용이지만 다시 정리 해보자..
C++의 템플릿
사용자가 원하는 타입을 넣어주면 알아서 코드를 찍어내는 틀이다.
class template
클래스 템플릿
std::vector와 비슷한 역할을 하는 myVector 라는 클래스로 설명하겠다..
template <typename T>
class myVector {
T* data;
int capacity;
...
}위 코드에서 template <typename T> 라는 부분은.. 템플릿 문장이다.
아래에 정의되는 myVector라는 클래스에 대해 템플릿을 정의하고,
템플릿 인자로 T를 받게 되며, T는 반드시 어떤 타입 이름임을 명시한다.
template <class T> 위 처럼 쓰기도 하는데 template <typename T> 와 기능상 정확히 동일하다.
과거 C++에서는 template 인자로 class 키워드를 사용했지만,
혼동을 막기위해 typename 키워드를 만들었고 하위 호환성을 위해 남겨두었다.
-> typename 키워드를 사용하자.
그러면 계속해서 알아보자..
class template instantiation
클래스 템플릿 인스턴스화
myVector<int> v1;
myVector<std::string> v2;위와 같이 사용하면 되며..
myVector 의 템플릿 인자에 타입(int, std::string)을 전달하면,
컴파일러는 타입을 보고 실제 코드를 생성한다.
(int의 경우 T 대신 int가 들어간 코드가 생성된다.)
이렇게 클래스 템플릿에 인자(타입)을 전달하여 실제 코드가 생성되는 것을
클래스 템플릿 인스턴스화 라고 부른다.
template specialization
템플릿 특수화
템플릿 타입에 따라 다르게 처리하고 싶을 때는 어떻게 할까..
아래와 같이 정의하면 된다.
//일반적인 경우 template <typename A, typename B, typename C> class temp { ... }; //A와 C가 각각 int 타입, double 타입일 경우엔 따로 처리하고 싶어 template <typename B> class temp<int, B, double> { ... }; //A, B, C가 모두 int 타입일 경우엔 이렇게 처리하고 싶어.. template <> class temp<int, int, int> { ... };
마지막 template을 보면 template <> 이라고 되어있다.
전달하는 템플릿 인자가 없더라도 template<> 이라고 남겨줘야한다.
타입에 따라.. 템플릿을 모두 작성하려면 번거롭고 힘들 수도 있다..
아래 포스팅을 보고 생각해보자.
https://starryeye.tistory.com/50?category=1090077
Function template
함수 템플릿
이번에는 함수 단위로 사용할 수 있는 템플릿이다.
template <typename T> T findMin(T& a, T& b) { if(a > b) return b; else return a; } int main() { int a = 1; int b = 2; int c = findMin(a, b); cout << c << endl; }
위 코드의 findMin 함수도 인스턴스화 되기 전까지는 컴파일 시점에 아무런 코드로 변환 되지 않는다.
함수 템플릿은
클래스 템플릿을 인스턴스화 할때 처럼
findMin<int>(a, b); 를 안해줘도 되는데..
이는 a, b 타입을 보고 컴파일러가 findMin<int>(a, b); 로 인스턴스화 해주기 때문이다.
<참고>
아래와 같이 템플릿이 정의 되어있을 경우에는 <> 를 생략 할 수 없다.
num을 non-type template arguments(타입이 아닌 템플릿 인자) 라 부른다.
template <typename T, int num> T add_num(T t) { return t + num; } int main() { int x = 1; cout << add_num<int, 10>(x) << endl; }
템플릿 인자로 전달할 수 있는 타입..
bool, char, int, long 등 (float, double 제외)
포인터 타입, enum, std::nullptr_t
그런데.. 함수 파라미터에 티폴트 인자를 넣어줄 수 있듯이..
템플릿에도 동일한 기능이 제공된다.
template <typename T, int num = 10>
T add_num(T t) {
...
}위와 같이 해놓으면 add_num(1); 처럼 <>을 생략 가능하다.
(컴파일러가 deduction 해줌)
이제 함수 템플릿의 대표적인 예시를 한번 보고 끝내자..
대표적 예시
std::array<int, 3> arr = {1, 2, 3}; std::array를 사용할 때, array의 크기를 템플릿 인자를 통해 전달 할 수 있다.
(컴파일 시점에 배열 크기 정해짐, 런타임시점에 동적으로 크기가 할당되는 것이 아니다)
-> 그리고.. 해당 타입은 std::array가 아닌.. std::array<int, 3> 이라는 타입이다.
-> 그러면 쓰기 힘들겠다..
template <typename T>
void addArray(T& arr) {
for(int i = 0; i < arr.size(); i++) {
arr[i]++;
}
}-> 위와 같이 이 역시.. template으로 만들어
-> std::array<int, 3>을 위한 함수, std::array<int, 5>을 위한 함수를 따로 만들 필요가 없다.
<주의>
template <typename T> std::size_t retSize(T& t) { return t.size(); }
참고로 위와 같은 템플릿이 있을 때,
T라는 타입이 class가 아니거나..
size()라는 함수가 정의 되지않은 class 이면..
당연하게도.. 컴파일 오류가 난다.
(컴파일 시점에 템플릿 인스턴스화할 때 문제가 발생하기 때문..)
대표적 예시 2
algorithm 헤더에 정의되어 있는
sort 함수이다.
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);더 자세한 정의 : https://www.cplusplus.com/reference/algorithm/sort/
sort() 함수 세번째 파라미터로
개발자가 구현한 static 비교 함수 또는 greater<>() 또는 less<>()를
함수 템플릿 class Compare 인자로 넘겨주면..
interator first, last 범위내 원소들이 정렬 될 수 있도록 한다.
'C++' 카테고리의 다른 글
[Modern C++ 정리] Temporary 2 (0) 2022.09.05 [Modern C++ 정리] Temporary 1 (0) 2022.09.05 [Effective Modern C++] 항목 8 (0) 2022.08.14 [Effective Modern C++] 항목 5 (0) 2022.08.14 [C++] move와 copy (0) 2022.07.15 다음글이전글이전 글이 없습니다.댓글