가변인자 템플릿(Variadic template)
-
C++11부터 지원되는 문법
-
가변인자 템플릿(클래스 템플릿, 함수 템플릿)의 기본 모양
-
가변인자 템플릿의 인자 "Types"는 여러개의 타입을 나타냄
-
가변인자 함수 템플릿의 인자인 "args"안에는 여러개의 값이 들어있고 "Parameter Pack"이라고 함
#include <iostream>
using namespace std;
// 가변인자 클래스 템플릿.
template<typename ... Types> class tuplex
{
};
// 가변인자 함수 템플릿
template<typename ... Types>
void foo(Types ... args)
{
}
int main()
{
// 가변인자 클래스 템플릿(타입 생략, 복수의 타입까지...)
tuplex<> t0p;
tuplex<int> t1;
tuplex<int, char> t2;
// 가변인자 함수 템플릿(인자 생략, 복수의 인자까지...)
foo();
foo(1);
foo(1, 3.4, "A");
}
Parameter Pack
-
가변인자 템플릿으로 전달받은 파라미터 집합을 Parameter Pack이라 함
-
sizeof...(args), sizeof...(Types) 함수를 이용해서 Parameter Pack 요소의 갯수를 얻어 올 수 있음
-
goo(args...); 받은 Parameter Pack을 다시 전달할때 요소 전체를 풀어쓰는 방법을 Pack Expansion이라 함
#include <iostream>
using namespace std;
// Pack expansion을 통해 Parameter Pack을 전달 받을 함수
void goo(int n, double d, const char* s)
{
cout << "goo : " << n << ", " << d << ", " << s << endl;
// 1, 3.4, "AAA"
}
// 가변인자 함수 템플릿
template<typename ... Types>
void foo(Types ... args)
{
// args : Parameter Pack
cout << sizeof...(args) << endl; // 3
cout << sizeof...(Types) << endl; // 3
//goo(args); // Error
goo(args...); // Pack expansion
// goo( 1, 3.4, "AAA")
}
int main()
{
//foo();
//foo(1);
foo(1, 3.4, "AAA");
// Types : int, double, const char*
// args : 1, 3.4, "AAA"
}
Pack Expansion
-
Parameter Pack을 사용하는 패턴에 "..." 붙이면 해당 패턴이 ',' 구분자로 확장되는 형태임
-
args이 1, 2, 3을 가지고 있을때
-
args... -> 1, 2, 3
-
(--args)... -> 0, 1, 2
-
func(args)... -> func(1), func(2), func(3)
-
func(args...) -> func(1, 2, 3)
-
func2(func(args...)) -> func2(func(1, 2, 3))
-
func2(func(args)...)) -> func2(func(1), func(2), func(3))
-
-
Pack Expansion은 함수 호출 인자 또는 list 초기화를 사용한 표현식에서만 사용할 수 있음
-
배열 이용
-
컴파일러에 따라 빈값이 허용 안될 수 있으므로 첫번째 요소를 더미로 0으로 지정
-
함수가 반환 타입이 void 경우 대비해서 대체 반환값 (x, 0) 패턴 사용
-
int x[] = { 0, (print(args), 0)... };
-
-
-
초기화 리스트 이용
-
빈값이 허용 됨으로 배열에 비해서 첫번째 요소 더미 0을 생략 할 수 있음
-
initializer_list<int> e = { (print(args), 0)... };
-
-
#include <iostream>
using namespace std;
void goo(int n, double d, const char* s)
{
cout << "goo : " << n << " " << d << " " << s << endl;
}
int hoo(int a) { return -a; }
int print(int a)
{
cout << a << ", ";
return 0;
}
template<typename ... Types>
void foo(Types ... args)
{
int x[] = { args... }; // Pack expansion
for (auto n : x)
cout << n << endl;
//print(args); // Error(함수 호출 인자 or list 초기화가 아님)
//print(args...); // Error(함수 호출 인자 or list 초기화가 아님)
//print(args)...; // Error(함수 호출 인자 or list 초기화가 아님)
// 배열 이용
int ea[] = { 0, (print(args), 0)... };
// 초기화 리스트 이용
initializer_list<int> ei = { (print(args), 0)... };
}
int main()
{
foo(1, 2, 3);
// Types : int, int, int
// args : 1, 2, 3
}
Expansion 예제
#include <iostream>
using namespace std;
template<typename ... Types> void foo(Types ... args)
{
// Types : int, double
int x[] = { args... };
pair<Types...> p1; // pair<int, double> // OK
tuple<Types...> t1; // tuple<int, double> // OK
tuple<pair<Types...>> t2; // tuple<pair<int, double>> // OK
tuple<pair<Types>...> t3; // tuple<pair<int>, pair<double>> // Error
tuple<pair<int, Types>...> t4; // tuple<pair<int, int>, pair<int, double>> // OK
pair<tuple<Types...>> p2; // pair<tuple<int, double>> // Error
pair<tuple<Types>...> p3; // pair<tuple<int>, tuple<double>> // OK
}
int main()
{
foo(1, 3.4);
// args : 1, 3.4
// Types : int, double
}
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 가변인자 템플릿(Variadic template) 함수 리턴타입 구하기 (0) | 2021.01.06 |
---|---|
C++ 가변인자 템플릿(Variadic template), fold expression(C++17) (0) | 2021.01.06 |
C++ 템플릿 type_traits(C++11 표준 remove_pointer, is_pointer) (0) | 2021.01.04 |
C++ 템플릿 traits(함수 반환 값/파라미터) (0) | 2021.01.04 |
C++ 템플릿 type modification(remove_pointer) (0) | 2021.01.04 |