※ LIG Nex1 The SSEN Embedded SW School에서 진행된 내용을 정리한 포스팅입니다.
템플릿
: 코드 일반화에 사용된다.
동작이 동일한 코드의 타입을 가상의 타입 이름으로 작성하여 사용 시 각 인자의 타입에 맞는 구현을 찾아간다.
템플릿 함수
- 컴파일러가 템플릿 코드를 컴파일 하면 호출된 코드의 파라미터를 확인하여 가상의 타입 이름을 해당 타입 이름으로 치환한 함수를 오버로딩 하여 제공한다.
- 실행 시 파라미터의 타입과 동일한 함수를 호출한다.
함수를 대상으로 하는 템플릿
template <typename T>
T Add(T num1, T num2) {
return num1 + num2;
}
- 호출 방법
- 전달한 인자에 맞는 템플릿을 호출한다.
int main() {
cout << Add(15, 20) << endl;
cout << Add(1.5f, 2.0f) << endl;
cout << Add(1.5, 2.0) << endl;
}
- 컴파일러는 함수 템플릿과 호출된 함수의 파라미터 타입을 보고 템플릿 함수를 생성한다.
- 함수 템플릿 != 템플릿 함수
Add(15, 20); // int 타입으로 템플릿 함수 생성
Add(2.3, 4.2); // double 타입으로 템플릿 함수 생성
- 특정 자료형에 대한 처리를 다르게해줄 경우, 구현을 명시적으로 해주면 해당 자료형에 대해서 템플릿 함수를 작성해주지 않는다.
- Max 함수의 특수화 예제
- template으로 작성된 Max를 char * 형으로 호출하게 된다면 주소값을 비교하여 큰 값을 반환하는 엉뚱한 동작을 할 것이다.
- 특정 자료형에 대한 동작을 직접 구현하여 해결해야 한다.
// template function
template <typename T>
T Max(T a, T b) {
return a > b ? a : b;
}
// template specialization
template <>
char *Max(char a, char b) {
return strlen(a) > strlen(b) ? a : b;
}
- 사용자 정의 클래스 등을 타입으로 사용할 때 대입 연산자 =, 파이프라인 연산자 << 등을 클래스 안에 오버라이딩 해주어야 동작하는 경우가 있다.
template <typename T>
class Point {
private:
T xpos, ypos;
public:
...
}
클래스 템플릿의 부분 특수화
- 특정 자료형을 가진 객체에 대한 처리를 다르게 해주기 위해 사용한다.
- 함수 템플릿의 특수화와 사용하는 이유와 동일하다.
template<typename T1, typename T2>
class MyTuple {...}; // 두 가지 타입의 자료를 저장하는 MyTuple
template<>
class MyTuple<char, int> {...}; // char, int에 대한 특수화
template<typename T>
class MyTuple<t, int> {...}; // int 한 가지 타입에 대한 특수화
- 더 구체적인 선언이 우선된다.
- <char, int>와 <T, int>가 선언되었을 때, 전자가 우선된다.
템플릿 매개변수의 default 값 지정
- STL의 stack 구현 일부를 살펴보자
- stack에서 사용하는 container의 기본 값을 deque으로 지정하고 있음을 확인할 수 있다.
- https://en.cppreference.com/w/cpp/container/stack
template<
class T,
class Container = std::deque<T>
> class stack;
+ STL 내부 소스코드
더보기
template <class _Tp, class _Container = deque<_Tp> >
class _LIBCPP_TEMPLATE_VIS stack;
/* code */
template <class _Tp, class _Container /*= deque<_Tp>*/>
class _LIBCPP_TEMPLATE_VIS stack {
public:
typedef _Container container_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::reference reference;
typedef typename container_type::const_reference const_reference;
typedef typename container_type::size_type size_type;
static_assert((is_same<_Tp, value_type>::value), "");
protected:
container_type c;
public:
_LIBCPP_HIDE_FROM_ABI stack() _NOEXCEPT_(is_nothrow_default_constructible<container_type>::value) : c() {}
_LIBCPP_HIDE_FROM_ABI stack(const stack& __q) : c(__q.c) {}
_LIBCPP_HIDE_FROM_ABI stack& operator=(const stack& __q) {
c = __q.c;
return *this;
}
/* code */
_LIBCPP_HIDE_FROM_ABI void pop() { c.pop_back(); }
_LIBCPP_HIDE_FROM_ABI void swap(stack& __s) _NOEXCEPT_(__is_nothrow_swappable<container_type>::value) {
using std::swap;
swap(c, __s.c);
}
_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; }
template <class _T1, class _OtherContainer>
friend bool operator==(const stack<_T1, _OtherContainer>& __x, const stack<_T1, _OtherContainer>& __y);
template <class _T1, class _OtherContainer>
friend bool operator<(const stack<_T1, _OtherContainer>& __x, const stack<_T1, _OtherContainer>& __y);
};
stack 내부의 container는 기본 값으로 deque로 지정되어있고, c라는 이름으로 접근할 수 있는 것을 볼 수 있습니다.
보십시오. pop의 구현이 c의 pop_back()을 호출할 뿐이라는 것을!
+ 비교해서 보면 좋을 것 같아 이전에 작성한 템플릿 정리를 첨부합니다.
[C++] 36.Unmanaged Programming: 템플릿 프로그래밍
C++ 템플릿과 STL 컨테이너템플릿(Template) 기본 개념C++에서의 템플릿은 코드의 재사용성을 높이기 위한 강력한 도구이다.템플릿은 함수나 클래스를 정의할 때 특정한 자료형에 의존하지 않고 일
bitbit-merry-go-round.tistory.com
※ 질문, 개선점, 오류가 있다면 댓글로 남겨주세요 :)
'Programming Language > C++' 카테고리의 다른 글
| [TheSSEN/C++] 12. 파일 입출력 (0) | 2025.01.31 |
|---|---|
| [TheSSEN/C++] 11. 예외 처리 (0) | 2025.01.31 |
| [TheSSEN/C++] 9. 연산자 오버로딩 (0) | 2025.01.27 |
| [TheSSEN/C++] 8. 다형성 (0) | 2025.01.27 |
| [TheSSEN/C++] 7. 상속 (0) | 2025.01.27 |