+ 이 글은 작성자가 직접 공부하고 복습하며 작성한 글입니다. 만약 직접 작성하지 않았다면, 꼭 출처를 밝히겠습니다!
+ 이 글은 개인적인 공부를 바탕으로 작성되었기에, 틀린 부분이 있을 수 있으며, 틀린 부분이 있다면 알려주시면 감사하겠습니다!
+ 이 글을 다른 곳으로 가져가신다면, 꼭 출처를 남겨주세요~
+ '참고사이트'는 공부하기 위해 참고한 사이트들을 모아 둔 것입니다.
+ 혹시라도 문제가 된다면 바로 조취를 취할테니, 말해주시면 감사하겠습니다!
코딩을 하다보면, 라이브러리로 구현된 함수 중, Parameter의 갯수에 상관없이 사용할 수 있는 함수들을 많이 보게됩니다. 대표적으로 printf(...)와 같은 출력문들이 그러한데요, 이러한 함수들은 구현될 때, 모든 경우에 대해서 overloading하는 것이 아닙니다. "Parameter pack"을 이용하여, 함수를 실행시키는 것이죠!!
[Parameter Pack]
+ 이름 그대로 인자들의 묶음을 나타냅니다.
+ 인자들을 묶어서 하나의 인자로 취급하니, 여러 인자를 한 번에 사용할 수 있습니다.
+ Parameter pack은 말 그대로 인자들의 묶음으로, 따로 자르거나 내부를 꺼내어 사용할 수 없습니다. 그냥 그 자체로 사용됩니다.
[Syntax]
'
type...Args
typename | class...Args
template<parameter-list> typename|class...Args
Args...args
'
+ 예시
'
template<class ... Types> struct Tuple {}; Tuple<> t0; // Types contains no arguments Tuple<int> t1; // Types contains one argument: int Tuple<int, float> t2; // Types contains two arguments: int and float Tuple<0> error; // error: 0 is not a type
template<class ... Types> void f(Types ... args); f(); // OK: args contains no arguments f(1); // OK: args contains one argument: int f(2, 1.0); // OK: args contains two arguments: int and double
'
+ Parameter pack을 사용할 때, 해당 pack 변수는 인자가 없는 상황부터 인지하게 됩니다.
`
template<typename... Args>
void temp(int value, Args... args){...}
// Can Use : temp(1);, temp(1,2);, temp(1,2,"asdf");
// Can't Use : temp();
`
+ 일단 간단히 사용되는건 이렇고, 좀 더 자세한 것은 날잡아서 더 공부해야할 것 같습니다.
+ printf(...)와 같은 출력문에서 많이 사용된다고 했었는데요, 예시로 한 번 만들어 보겠습니다!
'
#include <iostream> void tprintf(const char* format) // base function { std::cout << format; } template<typename T, typename... Targs> void tprintf(const char* format, T value, Targs... Fargs) // recursive variadic function { for ( ; *format != '\0'; format++ ) { if ( *format == '%' ) { std::cout << value; tprintf(format+1, Fargs...); // recursive call return; } std::cout << *format; } } int main() { tprintf("% world% %\n","Hello",'!',123); return 0; }
output : Hello world! 123
'
1) format변수로 나타낼 문장의 위치를 잡습니다. 그리고 value로 다음으로 출력될 변수를 지정하고, 마지막 parameter pack으로 출력될 변수들을 저장하면됩니다.
2) 한 칸씩 전진하면서 구분자를 찾고, 해당 구분자가 나오면 value를 출력해줍니다.
3) value를 출력하고나서는 다음 출력될 변수를 앞으로 당기기 위해 함수를 recursive합니다.
4) 마지막으로, value가 없는 상황을 대비해서 format만 남은 함수를 overloading해줍니다.
- Overloading을 해주지 않으면, 인자가 하나밖에 없는 상황에선 맞지않는 함수로 인식해 compile error가 발생합니다.
[resursive]
+ 왜 recursive를 해주는지 의아하실 수 있습니다. 그 점을 설명하자면, parameter pack은 그 내부를 하나하나 사용할 수 있는 변수가 아닌, 인수의 집합, 그 자체입니다. 따로 나눌수도 없이, 그냥 어떤 type의 변수들을 가지고 있다는 덩어리죠. 그렇기에 자동적으로 구분해서 사용할 수 있게 만들어야합니다. 그러한 방법으로 recursive를 사용한 것이죠. 위의 함수를 보게되면, recursive를 해주는 부분에 value가 없고 바로 parameter pack이 있습니다. 저렇게 하면 자동으로 parameter pack의 첫 번째 변수가 value로 가게 되는 것이죠. 그림으로 보여드리면
tprintf(1,2,3,4); //format : 1, value : 2, Targs : 3,4
그리고 다음 recursive를 하게 될 때는,
tprintf(1`,3,4); // format : 1`, value : 3, Targs:4
가 됩니다.
즉, 자동으로 parameter pack의 인자들을 하나하나 잘라서 사용하게 되는 것이죠. 이렇기에 recursive를 사용한 것입니다.
*** 참고해야하는 점
- parameter pack은 따로 내부를 자르거나 꺼내서 사용할 수 없습니다. 그 자체가 변수들을 가지고 있는 덩어리로 취급됩니다.
** 참고사이트 **
- http://en.cppreference.com/w/cpp/language/parameter_pack
- https://stackoverflow.com/questions/22968182/is-it-possible-to-typedef-a-parameter-pack
-
-
Copyright © -강정이좋아- 무단 전재 및 재배포는 하지 말아주세요.
'재료들 > C, C++(STL 포함)' 카테고리의 다른 글
Q. 변수 선언부분이 실행시간에 얼마나 영향을 줄까? (0) | 2018.07.02 |
---|---|
[STL] Vector에 관해서 (0) | 2018.04.14 |
[Error] Visual Studio Error (추가 중) (0) | 2018.04.14 |
[Override][Overloading] 함수 재정의 (0) | 2018.04.14 |
[Header] 헤더 재정의 방지(include guard, pragma once) (0) | 2018.04.14 |