1. 가변인자(Variable argument)
=> 변수의 개수가 변하는 인자
=> 함수나 템플릿의 파라미터로 원하는 만큼의 갯수를 넣을 수 있는 것
=> 마지막 멤버가 (...)인 선언
=> #include <cstdarg>를 사용(C는 stdarg.h)
=> 순서
-> 1. 인수에 Access 전에 va_list 변수로 목록 표시 설정
-> 2. va_arg 매크로를 통하여 인수에 엑세스
-> 3. va_arg 매크로를 원하는 식에 사용하여 얻은 결과를 명시적 캐스팅
-> 4. va_end로 인수처리 종료
#include<iostream>
#include<cstdarg>
using namespace std;
void Func(int args, ...)
{
va_list v1;
va_start(v1, args);
for(int i = 0; i<args; ++i)
{
if(i%2 == 0)
int temp = va_arg(ap,int);
else
int temp = va_arg(ap, double);
cout << "args : " << args << " : " << temp << endl;
}
va_end(v1);
}
2. 가변인자 템플릿(Variadic template)
=> Typename T는 여러개의 타입을 말함
=> C++11부터 지원
#include<iostream>
using namespace std;
template<typename ... T>
class A
{
};
template<typename ... T>
void Func_A(T ... args)
{
}
int main()
{
// Class Template
A<> a;
A<int> b;
A<int, char> c;
// Function Template
Func_A();
Func_A(1);
Func_A(1,"B");
return 0;
}
=> Parameter Pack이 존재
-> Parameter Pack : 가변인자 함수 템플릿의 인자 args의 파라미터 집합
-> sizeof...(args)로 사이즈를 얻을 수 있음
-> Pack Expansion : 함수호출 인자 혹은 list 초기화를 사용한 식에서만 사용 가능
3. Pack Expansion
=> 줄임표(...)를 통하여 하나 이상의 Parameter pack을 포함하는 표현식
template<class...T>
void func(T...a)
{
}; // T pack의 확장
template<class...U>
void func1(U...b)
{
func(b...);
}; // U pack의 확장
=> 함수 호출 인자 또는 list초기화를 사용한 표현식에서 사용
-> Expression list : 스위치 안에 pack expansion args 사용
#include <cstdio>
#include <cassert>
template<class...A> void func1(A...arg){
assert(false);
}
void func1(int a1, int a2, int a3, int a4, int a5, int a6){
printf("call with(%d,%d,%d,%d,%d,%d)\n",a1,a2,a3,a4,a5,a6);
}
template<class...A> int func(A...args){
int size = sizeof...(A);
switch(size){
case 0: func1(99,99,99,99,99,99);
break;
case 1: func1(99,99,args...,99,99,99);
break;
case 2: func1(99,99,args...,99,99);
break;
case 3: func1(args...,99,99,99);
break;
case 4: func1(99,args...,99);
break;
case 5: func1(99,args...);
break;
case 6: func1(args...);
break;
default:
func1(0,0,0,0,0,0);
}
return size;
}
int main(void){
func();
func(1);
func(1,2);
func(1,2,3);
func(1,2,3,4);
func(1,2,3,4,5);
func(1,2,3,4,5,6);
func(1,2,3,4,5,6,7);
return 0;
}
//출처 : https://www.ibm.com/docs/en/zos/2.3.0?topic=only-variadic-templates-c11
-> Initializer list : res의 initializer에서 Pack expansion args 사용
#include <iostream>
using namespace std;
void printarray(int arg[], int length){
for(int n=0; n<length; n++){
printf("%d ",arg[n]);
}
printf("\n");
}
template<class...A> void func(A...args){
const int size = sizeof...(args) +5;
printf("size %d\n", size);
int res[sizeof...(args)+5]={99,98,args...,97,96,95};
printarray(res,size);
}
//출처 : https://www.ibm.com/docs/en/zos/2.3.0?topic=only-variadic-templates-c11
-> Base specifier list : base C에서 Pack expansion 확장
#include <iostream>
using namespace std;
struct a1{};
struct a2{};
struct a3{};
struct a4{};
template<class X> struct baseC{
baseC() {printf("baseC primary ctor\n");}
};
template<> struct baseC<a1>{
baseC() {printf("baseC a1 ctor\n");}
};
template<> struct baseC<a2>{
baseC() {printf("baseC a2 ctor\n");}
};
template<> struct baseC<a3>{
baseC() {printf("baseC a3 ctor\n");}
};
template<> struct baseC<a4>{
baseC() {printf("baseC a4 ctor\n");}
};
template<class...A> struct container : public baseC<A>...{
container(){
printf("container ctor\n");
}
};
//출처 : https://www.ibm.com/docs/en/zos/2.3.0?topic=only-variadic-templates-c11
-> Member initializer list : class template container의 initializer 목록에서 Pack expansion 사용
#include <iostream>
using namespace std;
struct a1{};
struct a2{};
struct a3{};
struct a4{};
template<class X> struct baseC{
baseC(int a) {printf("baseC primary ctor: %d\n", a);}
};
template<> struct baseC<a1>{
baseC(int a) {printf("baseC a1 ctor: %d\n", a);}
};
template<> struct baseC<a2>{
baseC(int a) {printf("baseC a2 ctor: %d\n", a);}
};
template<> struct baseC<a3>{
baseC(int a) {printf("baseC a3 ctor: %d\n", a);}
};
template<> struct baseC<a4>{
baseC(int a) {printf("baseC a4 ctor: %d\n", a);}
};
template<class...A> struct container : public baseC<A>...{
container(): baseC<A>(12)...{
printf("container ctor\n");
}
};
//출처 : https://www.ibm.com/docs/en/zos/2.3.0?topic=only-variadic-templates-c11
-> Template argument list : Pack expansion C...는 class template container에 대한 template argument list의 context에서 확장
#include <iostream>
using namespace std;
template<int val> struct value{
operator int(){return val;}
};
template <typename...I> struct container{
container(){
int array[sizeof...(I)]={I()...};
printf("container<");
for(int count = 0; count<sizeof...(I); count++){
if(count>0){
printf(",");
}
printf("%d", array[count]);
}
printf(">\n");
}
};
template<class A, class B, class...C> void func(A arg1, B arg2, C...arg3){
container<A,B,C...> t1; // container<99,98,3,4,5,6>
container<C...,A,B> t2; // container<3,4,5,6,99,98>
container<A,C...,B> t3; // container<99,3,4,5,6,98>
}
-> Exception specification list : Pack expantion X...가 exception specification list에서 확장
struct a1{};
struct a2{};
struct a3{};
struct a4{};
struct a5{};
struct stuff{};
template<class...X> void func(int arg) throw(X...){
a1 t1;
a2 t2;
a3 t3;
a4 t4;
a5 t5;
stuff st;
switch(arg){
case 1:
throw t1;
break;
case 2:
throw t2;
break;
case 3:
throw t3;
break;
case 4:
throw t4;
break;
case 5:
throw t5;
break;
default:
throw st;
break;
}
}
'C++ > Tips' 카테고리의 다른 글
[C++] Try / Catch _2 (0) | 2021.06.24 |
---|---|
[C++] Predefined Macro (0) | 2021.06.23 |
[C++] New_2 (0) | 2021.06.21 |
[C++] Union (0) | 2021.06.18 |
[c++] inline (0) | 2021.06.16 |