C++11 가변 인자 템플릿
[The C++ Programming Language에서 발췌]
템플릿은 임의의 타입의 인자를 임의의 개수만큼 받아들이도록 정의될 수 있다. 그러한 템플릿을 가변 인자 템플릿이라고 부른다. 예를 들면 다음과 같다.
1 2 3 4 5 6 7 | void f() {} template<typename T, typename... Tail> void f(T head, Tail... tail) { g(head); t(tail...); } | cs |
가변 인자 템플릿 구현이 핵심은 그것에 인자 리스트를 전달할 때 첫 번째 인자를 나머지와 분리할 수 있다는 점에 주목하는 것이다. 여기서는 첫 번째 인자(head)에 뭔가를 한 다음, 나머지 인자(tail)로 재귀적으로 f()를 호출한다. 생략 부호...은 리스트의 '나머지'를 나타내기 위해 사용됐다. 물론 결국에 가서는 tail이 비워지게 되고 그것을 처리하기 위해 별도의 함수가 필요하게 될 것이다. 이 f(0는 다음과 같이 호출 될 수 있다.
1 2 3 4 5 6 7 8 9 | int main() { cout << "first: "; f(1, 2.2, "hallo"); cout << "\nsecond: "; f(0.2, 'c', "yuck!", 0, 1, 2); cout << "\n"; } | cs |
이렇게하면 순서대로 f(1, 2.2, "hello")를 호출하고, 이것은 call f(2.2, "hello")를 호출하고, 이것은 f("hello")를 호출하고, 이것은 f()를 호출하게 될 것이다. g(head)를 호출하면 어떻게 될 것인가? 당연히 실제 프로그램에서는 각 인자에 대해 우리가 원하는 처리를 수행하게 될 것이다. 예를 들면 그것의 인자(여기서는 head)를 출력하게 만들 수 있다.
1 2 3 4 5 | template<typename T> void g(T x) { cout << x << " "; } | cs |
이 경우 출력은 다음과 같을 것이다.
first : 1 2.2 hello
second: 0.2 c yuck! 0 1 2
f(0는 세 줄짜리 코드와 관련된 선언문으로 구현돼 있어 임의의 리스트나 값을 출력하는 printf()의 간단한 변형처럼 보인다.
가변 인자 템플릿의 강점은 우리가 그것에 부여하려는 어떤 인자든지 받아들일 수 있다는 점이다. 약점은 인터페이스의 타입 체크가 번거로운 템플릿 프로그램이 될 수도 있다는 점이다.