본문 바로가기

프로그래밍/C++

[C++11] 가변인자 탬플릿(Variadic Template)

C에서는 va_list 사용하여 가변인자를 처리해야 했다.

 

va_start 시작해서 va_end 끝내야 했으며어떤 타입인지 미리 알려주어야 하거나 모든 같은 형으로 가변인자를 사용해야 했다불편했고, C 마지막에 printf scanf 동작원리로 배운 뒤로는   적이 없던 개념이다.

 

C++ 와서 template 이라는 개념이 생겼다어떤 형태라도 template으로 뭉뚱그려 인자로 받을  있게  것이다그리고 가변인자 역시 template, 탬플릿으로 받을  있다.

 

가변인자 탬플릿은 다음과 같이 선언한다.

 

template<typename  첫번째_가변인자_인수>

반환형 함수명(첫번째_가변인자_인수... 가변인자_변수);

 

타입이름 앞에 ...  붙여 가변인자 탬플릿이라고 알려준다.

한글로  이름은 원하는 타입을 적으면 된다이렇게.

 

template<typename... Args>

void print(Args... args)

{

...

print(args...);

}

 

매개변수로  경우 변수명의  ... 붙여준다.

 

탬플릿 선언 : typename 뒤에 : typename... Ty

선언 : 타입의  ... : void print(Ty... ty);

사용 : 변수의  ... : print(ty...);

 

 

그런데 이렇게 쓰면 가변 인자의 내용을 확인을  하기 때문에 다음과 같이 ' 번째 가변 인자' 명시한다.

 

template<typename  첫번째_가변인자_인수typename... 가변인자_타입이름>

반환형  함수명( 첫번째_가변인자_인수 변수명가변인자_타입이름... 가변인자_변수);

 

예를 들면 이렇게 적으면 된다.

 

template<typename  Tytypename ... Args>

void print(Ty ty, Args...args)

 

'가변인자_변수'  번째 인자를 제외한 남은 가변인자를 가지고 '첫번째_가변인자_인수'  번째 인자로들어가게 된다이걸 재귀적으로 시행하는 것이 가변인자 함수의 핵심이다.

 그런데  예제에서는 Ty라는 탬플릿으로 인자를 받았기 때문에 Ty 어떤 타입인지   없다. C++ 공부한사람들이라면   사용할 만한 좋은 개념을  것이다.

 함수 오버로딩(overloading : 매개인자에 따라 함수명이 동일한 함수들을 재정의하는 기능) 사용하는 것이다.

 

그러면 사용 예는 다음과 같아진다.

 

void printType(int i);

void printType(string s);

...

 

template<typename  Tytypename ... Args>

void print(Ty ty, Args...args)

{

printType(ty);

print(args...);

}

 

이쯤에서 의문이 하나 생긴다가변인자가 하나씩 빠진 끝에 가변인자가 하나도 남지 않을 경우에는?

 

가변인자 탬플릿을 사용할 경우위와 같은 문제를 해결하기 위해 매개인자가 없거나마지막에  매개인자를가지는"가변인자 탬플릿 함수와 동일한 함수 이름을 가지는" 함수를 오버로딩 해야 한다 함수는 가변인자를 모두 처리한 뒤의 후처리를 위한 함수로, C에서의 va_end()  동일한 역할을 수행한다차이점은, va_end() 없다고 컴파일 에러를 부르지 않지만 가변인자 탬플릿은 원하는 형식의 함수가 오버로딩되지 않으면 컴파일 오류 뿜는다.

 가변인자의 마지막을 위한 함수는 대체로 매개인자가 없는 함수가 되는  좋은데  일반적인 후처리가 가능하기 때문이다마지막에  매개인자를 강제하는 방법을 쓰면  이외의 인자가 가변인자의 마지막에  컴파일 에러를 뿜는다유지보수에 문제가 생길 여지가 있기 때문에 매개인자가 없는 함수를 사용하는 것이 좋다.

 

예시는 다음과 같다.

 

// 1. 매개인자가 없는 오버로딩 함수

// 안정적인 후처리가 가능

void print();

 

void printType(int i);

void printType(string s);

...

 

template<typename  Tytypename ... Args>

void print(Ty ty, Args...args)

{

printType(ty);

print(args...);

}

 

// 2. 마지막 인자를 강제할 경우

// 마지막은 항상 int형으로만 받으려고 한다.

void print(int last_arg);

 

void printType(int i);

void printType(string s);

...

 

template<typename  Tytypename ... Args>

void print(Ty ty, Args...args)

{

printType(ty);

print(args...);

}

 

 마지막 매개인자를 강제하는 오버로딩의 인자는 여러 개가  수도 있다그러니까 마지막 매개인자 5개를 강제하는 함수를 작성할 수도 있다는 사실.

 

void print(int last_arg_01, int last_arg_02, constchar* last_arg_03, int last_arg_04);

다른 말로는 마지막 매개인자들의 순서에 따라 후처리를 다르게   수도 있다 뜻인데그런  하시는 분에게는   추천한다

 

자세한 내용을 원한다면 MSDN 참고하는  좋다한글 번역이   있다.

MSDN : https://msdn.microsoft.com/ko-kr/library/dn439779(v=vs.140).aspx

 

 

 

+) 매개인자는 오직 뒤에만 사용할  있다.

+) 매개인자의 사이즈는 sizeof...() 키워드로   있다.

+) 반환형이 const size_t 이기 때문에 배열을 선언할  있다.




질문은 댓글로 남겨주세요.