나는 생산성을 높여주는 템플릿을 좋아하는편이다.
그중 최신에 알게된 가변인자 템플릿을 무척 편리하게 써먹은 적이 있다.
가변인자 템플릿(Variadic template)은
printf에 사용해 왔던 가변 인자 함수(Variadic function)와 조금 닮은면이 있다. (va_list)
가변인자템플릿의 template... 을 파라미터팩(parameta pack) 이라고 불린다.
예제코드
#include "stdio.h"
#include "tchar.h"
typedef unsigned char BYTE;
class cPacket
{
public:
enum { BUFF_MAX = 1024 };
// 기본 생성자
cPacket()
: m_pCur(m_byBuff)
, m_pEnd(m_byBuff + BUFF_MAX)
{
memset(m_byBuff, 0, BUFF_MAX);
printf("init\n");
}
// 소멸자
~cPacket() {};
// 템플릿 가변인자 생성자
template <typename... pack> // 파라미터팩(parameta pack)
cPacket(pack... args) : cPacket()
{
// sizeof...(args) 로 가변인자의 사이즈도 알수있다.
printf("parameta pack size = %llu \n", sizeof...(args));
// 생성자를 재귀호출할순 없으니, 파라미터팩을 전달인자로 가지는 재귀함수를 호출하자.
push(args...);
end_push();
}
// 이 함수에 인자가 하나남을때까지 재귀호출된다.
template <typename T, typename... pack>
void push(T Data, pack... args)
{
push(Data);
push(args...); // 재귀호출
}
// 실제 처리되는 함수
template <typename T>
void push(T Data)
{
const int nSize = sizeof(T);
if (m_pCur + nSize > m_pEnd)
{
printf("overflow\n");
return;
}
memcpy(m_pCur, &Data, nSize);
m_pCur += nSize;
// 디버깅용 로그 1
printf("push:%d\n", Data);
}
// 버전에따라 파라미터가 빈 함수도 생성해야할때도 있다.
//void push(void) {}
void end_push(void)
{
m_pEnd = m_pCur;
m_pCur = m_byBuff;
// 디버깅용 로그 2
printf("push end\n");
}
template <typename T>
void pop(T& Data)
{
const int nSize = sizeof(T);
if (m_pCur + nSize > m_pEnd)
{
printf("overflow\n");
return;
}
memcpy(&Data, m_pCur, nSize);
m_pCur += nSize;
printf("pop:%d\n", Data);
}
private:
BYTE m_byBuff[BUFF_MAX];
BYTE* m_pCur;
BYTE* m_pEnd;
};
int main()
{
// 생성자로 int형 데이터 8개 입력
cPacket pk(0, 1, 2, 3, 4, 5, 6, 7);
int nFoo;
// 제대로 들어갔는지 확인해보자.
for (int i = 0; i < 9; ++i)
pk.pop(nFoo);
}
실행결과
init
parameta pack size = 8
push:0
push:1
push:2
push:3
push:4
push:5
push:6
push:7
push end
pop:0
pop:1
pop:2
pop:3
pop:4
pop:5
pop:6
pop:7
overflow
일부러 pop를 한번 더 실행해서 overflow를 확인해보았다.
이런식으로 패킷 함수를 만들어놓으면 앞으로가 편안할것이다. 흐믓
'C++' 카테고리의 다른 글
C++11 람다 함수 (Lambda Function) (0) | 2020.04.26 |
---|---|
C++11 stl에 추가된 emplace(insert), emplace_back(push_back) (0) | 2020.04.17 |
C++11 enum class (1) | 2020.04.12 |
유니코드 문자열 처리 (0) | 2020.04.12 |
printf문의 서식지정자 (0) | 2020.04.12 |