codenuri 강석민 강사 강의 내용기반으로 정리한 내용입니다.
result using variadic template
함수의 정보를 구하는 traits 만들기
- primary template 을 만들고 typedef T type 을 제공한다.
 - 함수 타입인 T 안에 있는 리턴 타입(double)을 얻을 수 있도록 부분 특수화한다.
- T -> R(A1, A2)
 
 - 인자 개수에 제한을 없애기위해서 가변 인자 템플릿 사용.
- T -> R(Types…)
 
 
#include <iostream>
using namespace std;
double hoo(short a, int b) {return 0;}
int goo() {return 0;}
template<typename T> struct result_type
{
	typedef T type;
}
template<typename R, typename ... Types> struct result_type<R(Types...)>
{
	typedef R type;
}
template<typename T>
void foo(const T& t)
{
	typename result_type<T>::type ret;
	cout << typeid(ret).name() << endl;
}
int main()
{
	foo(hoo);	// double
	foo(goo);	// int
}
result_type을 잘못사용했을 때 에러를 처리하는 방법
- typedef T type을 제공하지 않는다.
 - static_assert()를 사용해서 에러 메시지 출력
 - primary template 을 선언만 제공한다.
 
#include <iostream>
using namespace std;
double hoo(short a, int b) {return 0;}
int goo() {return 0;}
template<typename T> struct result_type 
//3 주석처리 : 선언부는 반드시 필요
/*
{
	// 1
	// typedef T type;
	// 2
	// static_assert(is_function<T>::value, "error");
}
*/
template<typename R, typename ... Types> struct result_type<R(Types...)>
{
	typedef R type;
}
template<typename T>
void foo(const T& t)
{
	typename result_type<T>::type ret;
	cout << typeid(ret).name() << endl;
}
int main()
{
	int n = 0;
	foo(n); // primary로 가서 그냥 int 나옴
}
argument using variadic template
함수의 정보를 구하는 traits 만들기
1.primary template 을 만들고 typedef T type 을 제공한다. 2.함수 타입인 T 안에 있는 함수 인자 타입을 얻을 수 있도록 부분 특수화한다.
- T -> R(A1, A2), T -> R(A1, Types…)
 
#include <iostream>
using namespace std;
double hoo(short a, int b, char c) {return 0;}
template<size_t N, typename T> struct argument_type
{
	typedef T type;
}
template<typename R, typename A1, typename ... Types>
struct argument_type<0, R(A1, Types...)>
{
	typedef A1 type;
}
template<typename T>
void foo(const T& t)
{
	typename argument_type<0, T>::type ret;
	cout << typeid(ret).name() << endl;
}
int main()
{
	foo(hoo);	// double
	foo(goo);	// int
}
argument type에 0을 전달하지 않고 1, 2 를 전했을 때 구하는법
3.N번째 인자 타입 구하는 방법
- 0번째 인자의 타입을 구하는 부분 특수화 작성
 - N번째 인자의 타입을 구하는 부분 특수화 작성하고 N==0이 될때까지 Recursive 를 사용한다(Recursive 사용시, 함수의 0번째 인자를 제거하고 N-1을 사용한다.)
 
argument_type<2, R(A1, A2, A3)>::type
재귀로 가면 앞에꺼 하나 버릴 수 있음
argument_type<1, R(A2, A3)>::type
argument_type<0, R(A3)>::type
0일 때는 부분 특수화 사용하니 type 구함
#include <iostream>
using namespace std;
double hoo(short a, int b, char c) {return 0;}
template<size_t N, typename T> struct argument_type
{
	typedef T type;
}
// N==0
template<typename R, typename A1, typename ... Types>
struct argument_type<0, R(A1, Types...)>
{
	typedef A1 type;
}
// N일때
template<size_t N, typename R, typename A1, typename ... Types>
struct argument_type<N, R(A1, Types...)>
{
	typedef typename argument_type<N-1, R(Types...)>::type type;
}
template<typename T>
void foo(const T& t)
{
	typename argument_type<2, T>::type ret;
	cout << typeid(ret).name() << endl;
}
int main()
{
	foo(hoo);	// double
	foo(goo);	// int
}
tuple using variadic template
tuple
- 서로 다른 타입의 객체를 N개 보관하는 템플릿.
 - 요소를 접근할 때는 get 을 사용한다.
 - C++11 부터 표준으로 제공. tuple 헤더
 
#include <iostream>
#include <tuple>
using namespace std;
int main()
{
	tuple<> t0;
	tuple<int> t1(1);
	tuple<int, double, int, char> t4(1, 3.4, 2, 'A');
	cout << get<2>(t4) << endl;	// 2
}
tuple 만들기.
1.가변 인자 템플릿을 사용해서 primary template 을 만든다.
#include <iostream>
#include <tuple>
using namespace std;
template<typename ... Types> struct xtuple
{
	static constexpr int N = 0;
}
int main()
{
	xtuple<> t0;
	xtuple<int> t1;
	xtuple<int, double, char> t3;
}
2.1개의 요소를 보관할 수 있도록 부분 특수화를 사용한다.
#include <iostream>
#include <tuple>
using namespace std;
template<typename ... Types> struct xtuple
{
	static constexpr int N = 0;
}
// 부분 특수화
template<typename T, typename ... Types> struct xtuple<T, Types...>
{
	T value;
	xtuple() = default;
	xtuple(const T& v) : value(v) {}
	static constexpr int N = 1;
}
int main()
{
	xtuple<> t0;
	xtuple<int> t1(3);
	xtuple<int, double, char> t3;
}
3.상속을 사용해서 N개를 보관할 수 있게 만든다.
#include <iostream>
#include <tuple>
using namespace std;
template<typename ... Types> struct xtuple
{
	static constexpr int N = 0;
}
// 부분 특수화
template<typename T, typename ... Types> struct xtuple<T, Types...> : public xtuple<Types...>
{
	T value;
	xtuple() = default;
	xtuple(const T& v, const Types& ... args) : value(v), xtuple<Types...>(args...) {}
	static constexpr int N = xtuple<Types...>::N + 1;
}
int main()
{
	xtuple<int, double, char> t3(1, 3.4, 'A');
	xtuple<double, char> t2;
	xtuple<char> t1;
}
4.생성자등 필요한 멤버를 추가한다.
다음꺼에 get을 이용해 tuple 에서 값을 꺼내는 코드 설명함