일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- #선물 #비트코인#알트코인#매매#코인#마진
- 오버로딩
- template
- trading view
- Tree
- Windows
- C++
- 전위
- BST
- Data Structure
- 숫자
- 문자열
- 후위
- SCM
- 선물
- 템플릿 함수화
- 이진 탐색 트리
- Python
- 순회
- Basic
- 자료구조
- 바이낸스
- array
- linked list
- mutable
- 트리
- 연결 리스트
- 알고리즘
- 비트코인
- 기초
- Today
- Total
Project Hub
14. template 본문
이전 글
2022.12.21 - [C++/c++ basic] - 13. 파일 입출력
13. 파일 입출력
이전 글 2022.12.21 - [C++/c++ basic] - 12. 입출력 (istream, ostream) 12. 입출력 (istream, ostream) 이전 글 2022.12.21 - [C++/c++ basic] - 11. virtual 함수와 다형성 11. virtual 함수와 다형성 이전 글 2022.12.21 - [C++/c++ basic] -
projecthub.tistory.com
C++ 템플릿 (template)
아래는 템플릿 형식으로 만든 vector 클래스다.
실제 사용 시, CVector<자료형> test_vector; 형식 들으로 사용이 되는데,
이러한 것을 클래스 템플릿 인스턴스화 라고 한다.
#pragma once
#include <iostream>
template <typename T>
class CVector
{
public:
CVector(int n = 1) : m_pData(new T[n]), m_iCapacity(n), m_iLength(0) {};
~CVector() { if (m_pData) delete[] m_pData; }
public:
void push_back(T s)
{
if (m_iLength >= m_iCapacity)
{
T* pTemp = new T[m_iCapacity * 2];
if (NULL != pTemp)
{
for (int i = 0; i < m_iLength; i++)
pTemp[i] = m_pData[i];
}
delete[] m_pData;
m_pData = pTemp;
m_iCapacity *= 2;
}
m_pData[m_iLength] = s;
m_iLength++;
}
void remove(int iIdx)
{
for (int i = iIdx + 1; i < m_iLength; i++)
m_pData[i - 1] = m_pData[i];
}
int size()
{
return m_iLength;
}
T operator[](int iIdx) { return m_pData[iIdx]; }
public:
T* m_pData;
int m_iCapacity;
int m_iLength;
};
템플릿 특수화 (template specialization)
아래와 같은 클래스 템플릿이 정의되어있을 때,
template<typename A, typename B, typename C>
class test {};
일부 겅우에 대해서 따로 처리를 할 수 있다.
template <typename B>
class test<int, B, double> {};
template <>
class test<int, int, double> {};
중요한 점은, 전달하는 템플릿 인자가 없더라도 특수화 하고 싶다면, template<> 라도 남겨줘야 한다는 점이다.
아래는 템플릿 특수화로 bool vector 클래스를 구현한 것이다.
CVector 클래스 호출 시, CVector<bool> 로 지정할 경우, 아래 클래스가 호출된다.
기존 vector 클래스
...
// 템플릿 특수화
template <>
class CVector<bool>
{
public:
CVector(int n = 1) : m_puiData(new unsigned int[n / 32 + 1]), m_iCapacity(n / 32 + 1), m_iLength(0) { for (int i = 0; i < m_iCapacity; i++) m_puiData[i] = 0; };
~CVector() { if (m_puiData) delete[] m_puiData; }
public:
void push_back(bool s)
{
if (m_iLength >= m_iCapacity * 32)
{
unsigned int* puiTemp = new unsigned int[m_iCapacity * 2];
if (NULL != puiTemp)
{
for (int i = 0; i < m_iCapacity; i++)
puiTemp[i] = m_puiData[i];
for (int i = m_iCapacity; i < m_iCapacity * 2; i++)
puiTemp[i] = 0;
}
delete[] m_puiData;
m_puiData = puiTemp;
m_iCapacity *= 2;
}
if (s)
m_puiData[m_iLength / 32] |= (1 << (m_iLength % 32));
m_iLength++;
}
void remove(int iIdx)
{
for (int i = iIdx + 1; i < m_iLength; i++)
{
if (m_puiData[i / 32] & (1 << i % 32))
{
m_puiData[(i - 1) / 32] |= (1 << (i - 1) % 32);
}
else
{
unsigned int all_ones_except_prev = 0xFFFFFFFF; // = 1111 1111 1111 1111 1111 1111 1111 1111
all_ones_except_prev ^= (1 << ((i - 1) % 32)); // ^= 연산은 다를 경우 1 반환
m_puiData[(i - 1) / 32] &= all_ones_except_prev;
}
}
m_iLength--;
}
int size()
{
return m_iLength;
}
bool operator[](int iIdx) { return (m_puiData[iIdx / 32] & (1 << (iIdx % 32))) != 0; }
public:
unsigned int* m_puiData;
int m_iCapacity;
int m_iLength;
};
함수 객체 (Function Object - Functor)
- 함수는 아니지만 함수인 척을 하는 객체
아래는 함수 객체에 대한 예시다.
추가로 struct Com1, Com2 로 선언을 한 부분이 있다.
c++ 에서 class 와 struct 는 똑같은 키워드다.
차이점은 struct는 디폴트로 public 이고, class는 디폴트로 private 라는 것이다.
따라서 struct 로 선언해서 public: 한줄 쓰는 것을 줄일 수 있다.
template <typename T>
class CVector
{
public:
CVector(int n = 1) : m_pData(new T[n]), m_iCapacity(n), m_iLength(0) {};
~CVector() { if (m_pData) delete[] m_pData; }
public:
void push_back(T s)
{
if (m_iLength >= m_iCapacity)
{
T* pTemp = new T[m_iCapacity * 2];
if (NULL != pTemp)
{
for (int i = 0; i < m_iLength; i++)
pTemp[i] = m_pData[i];
}
delete[] m_pData;
m_pData = pTemp;
m_iCapacity *= 2;
}
m_pData[m_iLength] = s;
m_iLength++;
}
void remove(int iIdx)
{
for (int i = iIdx + 1; i < m_iLength; i++)
m_pData[i - 1] = m_pData[i];
}
int size()
{
return m_iLength;
}
void swap(int iFirst, int iSecond)
{
T temp = m_pData[iFirst];
m_pData[iFirst] = m_pData[iSecond];
m_pData[iSecond] = temp;
}
T operator[](int iIdx) { return m_pData[iIdx]; }
public:
T* m_pData;
int m_iCapacity;
int m_iLength;
};
// 함수 객체 예시
struct Comp1
{
bool operator()(int a, int b) { return a > b; }
};
struct Comp2
{
bool operator()(int a, int b) { return a < b; }
};
template <typename Cont, typename Comp>
void bubble_sort(Cont& cont, Comp& comp)
{
for (int i = 0; i < cont.size(); i++)
{
for (int j = i + 1; j < cont.size(); j++)
{
if (!comp(cont[i], cont[j])) // comp 라는 객체가 마치 함수처럼 사용되고 있다.
cont.swap(i, j);
}
}
}
타입이 아닌 템플릿 인자
- 정수 타입들 (bool, char, int, long 등)
- 포인터 타입
- enum 타입
- std::nullptr_t (널 포인터)
template <typename T, int num> // int 형의 템플릿 인자
T add_num(T t)
{
return t + num;
}
디폴트 템플릿 인자
template <typename T>
struct Compare
{
bool operator()(const T& a, const T& b) { return a < b; }
};
template <typename T, typename Comp = Compare<T>> // 디폴트 템플릿 인자
T Min(T a, T b)
{
Comp comp;
if (comp(a, b)) // 함수처럼 사용
return a;
else
return b;
}
'C++ > c++ basic' 카테고리의 다른 글
13. 파일 입출력 (1) | 2022.12.21 |
---|---|
12. 입출력 (istream, ostream) (0) | 2022.12.21 |
11. virtual 함수와 다형성 (0) | 2022.12.21 |
10. 업 캐스팅 & 다운 캐스팅 (0) | 2022.12.21 |
9. 전위/후위 증감 연산자 오버로딩 & 첨자 연산자 오버로딩 (0) | 2022.12.21 |