codenuri 강석민 강사 강의 내용기반으로 정리한 내용입니다.
Typelist intro.
Andrei Alexandrescue, loki 라이브러리
Modern C++ Design 도 읽어보기
Typelist
- 값을 보관하지 않는다.
- N 개의 타입을 보관한다.
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
int main()
{
Typelist<int, double> t1;
Typelist<int, Typelist<int, double>> t2;
Typelist<int, Typelist<int, Typelist<int, double>>> t3;
}
Step2. NullType 와 매크로 도입
Typelist: 타입을 여러개 보관하는 type의 list(값이 아님.)
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
// 매크로 도입
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
int main()
{
Typelist<int, NullType> t1;
Typelist<int, Typelist<double, NullType>> t2;
Typelist<int, Typelist<double, Typelist<char, NullType>>> t3;
// 매크로 도입
TYPELIST_4(int, double, char, short) t4;
}
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
// 매크로 도입
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
//---------------------------------------------------------------------
template<typename T> class xtuple {};
int main()
{
// xtuple<int> t1;
xtuple<TYPELIST_3(int, double, char)> t1;
}
Typelist Length
#include <iostream>
using namespace std;
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
//---------------------------------------------------------------------
// Typelist의 요소 갯수 구하기.
// 1. 사용하는 모습을 보고 primary template 작성
template<typename T> struct Length
{
// enum { value = ? }; // constexpr value 를 요즘에는 많이 사용
}
// 2. 갯수를 구할 수 있도록 부분 특수화
template<typename T, typename U> struct Length<Typelist<T, U>>
{
enum { value = Length<U>::value + 1 };
}
// 3. 재귀를 종료 하기 위한 전문화
template<> struct Length<NullType>
{
enum { value = 0 };
}
template<typename T> void test()
{
cout << Length<T>::value << endl; // 4
};
int main()
{
test<TYPELIST_4(int, char, short, double)>();
}
TypeAt
#include <iostream>
using namespace std;
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
//---------------------------------------------------------------------
// Typelist의 N 번째 요소의 타입 구하기.
// 1. 사용하는 코드를 보고 primary template 작성
// T: Typelist
template<typename T, int N> struct TypeAt;
// 2. 원하는 타입을 구할 수 있도록 부분 특수화
// T: Typelist 의 요소 타입
/*
template<typename T, typename U, int N> struct TypeAt<Typelist<T, U>, N>
{
typedef ? type; // 여기서 현재 타입을 채울 수 없음
}
*/
// N==0 일때.
template<typename T, typename U, int N> struct TypeAt<Typelist<T, U>, 0>
{
typedef T type;
}
// N!=0 일때.
template<typename T, typename U, int N> struct TypeAt<Typelist<T, U>, N>
{
typedef typename TypeAt<U, N-1>::type type;
}
template<typename T> void test()
{
// typename TypeAt<T, 0>::type n;
typename TypeAt<T, 1>::type n;
cout << typeid(n).name() << endl;
};
int main()
{
test<TYPELIST_4(int, char, double, long)>();
}
Append
#include <iostream>
using namespace std;
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
//---------------------------------------------------------------------
// Typelist의 끝에 타입 추가하기
template<typeanme TL, typename T> struct Append;
// TL, T
// 1. NullType, NullType => NullType
template<> struct Append<NullType, NullType>
{
typedef NullType type;
}
// 2. NullType, 임의의 타입 => TypeList<임의의타입, NullType>
template<typename T> struct Append<NullType, T>
{
typedef TypeList<T, NullType> type;
}
// 3. NullType, TypeList<Head, Tail> => TypeList<Head, Tail>
template<typename Head, typename Tail> struct Append<NullType, TypeList<Head, Tail>>
{
typedef TypeList<Head, Tail> type;
}
// 4. TypeList<Head, Tail>, NullType => TypeList<Head, Tail>
template<typename Head, typename Tail> struct Append<TypeList<Head, Tail>, NullType>
{
typedef TypeList<Head, Tail> type;
}
// 5. TypeList<Head, Tail>, 임의의 타입 => Typelist<Head, Append<Tail, T>::type>
template<typename Head, typename Tail, typename T> struct Append<TypeList<Head, Tail>, T>
{
typedef Typelist<Head, Append<Tail, T>::type> type;
}
template<typename T> void test()
{
typename Append<T, int>::type t1;
cout << typeid(t1).name() << endl; // int, char, double, int, NULL
};
int main()
{
test<TYPELIST_4(int, char, double)>();
}
using Typelist
#include <iostream>
using namespace std;
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
// Holder : 임의의 타입의 data 하나 보관..
template<typename T> struct Holder
{
T value;
}
// GenScatterHierachy => MakeCode
template<typename T, template<typename> class Unit> class MakeCode : public Unit<T>
{
}
template<typename T, template<typename> class Unit> class MakeCode<NuullType, Unit>
{
}
int main()
{
Holder<int> h1;
MaekCode<int, Holder> mc1; // 기반 클래스 Holder<int> 이므로 Holder<int> 와 메모리 모양이 동일
MakeCode<double, Holder> mc2; // Holder<double>
MakeCode<NullType, Holder> mc3; // empty
}
#include <iostream>
using namespace std;
template<typename T, typename U> struct Typelist
{
typedef T Head;
typedef U Tail;
}
struct NullType{};
#define TYPELIST_1(T1) Typlelist<T1, NullType>;
#define TYPELIST_2(T1, T2) Typlelist<T1, Typelist<T2, NullType>>;
#define TYPELIST_3(T1, T2, T3) Typlelist<T1, Typelist<T2, Typelist<T3, NullType>>>;
#define TYPELIST_4(T1, T2, T3, T4) Typlelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType>>>>;
// Holder : 임의의 타입의 data 하나 보관..
template<typename T> struct Holder
{
T value;
}
// GenScatterHierachy => MakeCode
template<typename T, template<typename> class Unit> class MakeCode : public Unit<T>
{
}
template<typename T, template<typename> class Unit> class MakeCode<NuullType, Unit>
{
}
// MakeCode의 1번째 인자가 Typelist 일 때..
template<typename T, template<typename> class Unit>
//= MakeCode<int, Unit>, MakeCode<Typelist<double, NullType>
//= Holder<int>, MakeCode<double, Unit>, MakeCode<NullType, Unit>
//= Holder<int>, Holder<double>, empty
class MakeCode<Typelist<Head, Tail>, Unit> : public MakeCode<Head, Unit>, public MakeCode<Tail, Unit>
{
// int value;
// double value;
}
int main()
{
// MakeCode 의 1번째 인자가 Typelist 일 때..
// Typelist<int, Typelist<double, NullType>>
MakeCode<TYPELIST_2(int, double), Holder> m;
MaekCode<int, Holder> mc1; // Holder<int>
MakeCode<double, Holder> mc2; // Holder<double>
MakeCode<NullType, Holder> mc3; // empty
}