가변 템플릿은 c 에서 가변인자 함수에서#include <iostream>using namespace std;template <typename T>void print(const T& t){cout << t << endl;}template <typename First, typename... Rest>void print(const First& first, const Rest&... rest){cout << first << ", ";print(rest...); // recursive call using pack expansion syntax}int main(){print(100, 200, 201, 202, 300);print("first", 2, "third", 3.14159);}
//실행 결과
100, 200, 201, 202, 300
first, 2, third, 3.14159
참고 : https://msdn.microsoft.com/ko-kr/library/dn439779(v=vs.140).aspx
http://egloos.zum.com/Lusain/v/3158201
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 Ty, typename ... Args>
void print(Ty ty, Args...args)
'가변인자_변수'는 첫 번째 인자를 제외한 남은 가변인자를 가지고 '첫번째_가변인자_인수'만 첫 번째 인자로 들어가게 된다. 이걸재귀적으로 시행하는 것이 가변인자 함수의 핵심이다.
그런데 위 예제에서는 Ty라는 탬플릿으로 인자를 받았기 때문에 Ty가 어떤 타입인지 알 수 없다. C++을 공부한 사람들이라면 이 때사용할 만한 좋은 개념을 알 것이다.
함수 오버로딩(overloading : 매개인자에 따라 함수명이 동일한 함수들을 재정의하는 기능)을 사용하는 것이다.
그러면 사용 예는 다음과 같아진다.
void printType(int i);
void printType(string s);
...
template<typename Ty, typename ... Args>
void print(Ty ty, Args...args)
{
printType(ty);
print(args...);
}
이쯤에서 의문이 하나 생긴다. 가변인자가 하나씩 빠진 끝에 가변인자가 하나도 남지 않을 경우에는?
가변인자 탬플릿을 사용할 경우, 위와 같은 문제를 해결하기 위해 매개인자가 없거나, 마지막에 올 매개인자를 가지는,
"가변인자탬플릿 함수와 동일한 함수 이름을 가지는" 함수를 오버로딩 해야 한다.
이 함수는 가변인자를 모두 처리한 뒤의 후처리를 위한 함수로, C에서의 va_end() 와 동일한 역할을 수행한다.
차이점은, va_end()는 없다고 컴파일 에러를 부르지 않지만 가변인자 탬플릿은원하는 형식의 함수가 오버로딩되지 않으면 컴파일 오류를 뿜는다.
'프로그래밍(Programming) > c++, 11, 14 , 17, 20' 카테고리의 다른 글
클로져 객체의 복사 생성자와 소멸자 (0) | 2016.07.18 |
---|---|
shared_ptr 순환 참조의 문제 weak_ptr (0) | 2016.07.17 |
연산자 오버로딩 함수를 상속 받는 방법 using (0) | 2016.07.04 |
상속생성자(Inheriting Constructor) (0) | 2016.07.04 |
using 과 typedef , typedef 보다는 using (0) | 2016.07.04 |