forked from andrewprock/ustl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
typelist.h
219 lines (195 loc) · 7.96 KB
/
typelist.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// This file is part of the uSTL library, an STL implementation.
//
// Copyright (c) 2007 by Mike Sharov <[email protected]>
//
// This implementation is adapted from the Loki library, distributed under
// the MIT license with Copyright (c) 2001 by Andrei Alexandrescu.
#pragma once
#include "metamac.h"
#include "typet.h"
namespace ustl {
namespace tm {
/// The building block of typelists. Use it throught the Seq templates.
template <typename T, typename U>
struct Typelist {
using Head = T;
using Tail = U;
};
/// Namespace containing typelist-related functionality.
namespace tl {
//----------------------------------------------------------------------
// Seq template definitions. The macros expand to a spec per arg count
//
#define TL_MAX_SEQ_TYPES 9
#define TL_MAX_SEQ_SPECS 8
#define TL_SEQ_TYPE(n) T##n
#define TL_SEQ_TYPENAME(n) typename TL_SEQ_TYPE(n)
#define TL_SEQ_NULLTYPE_DEFAULT(n) TL_SEQ_TYPENAME(n)=NullType
#define TL_SEQ_TL_END(n) >
#define TL_SEQ_ONE_TYPELIST(n) Typelist<TL_SEQ_TYPE(n)
/// Creates a typelist from a sequence of types
template <COMMA_LIST(TL_MAX_SEQ_TYPES,TL_SEQ_NULLTYPE_DEFAULT)>
struct Seq {
using Type = COMMA_LIST(TL_MAX_SEQ_TYPES,TL_SEQ_ONE_TYPELIST),
NullType REPEAT(TL_MAX_SEQ_TYPES,TL_SEQ_TL_END);
};
#define TL_SEQ_SPEC(n) \
template <COMMA_LIST (n, TL_SEQ_TYPENAME)> \
struct Seq<COMMA_LIST (n, TL_SEQ_TYPE)> { \
using Type = COMMA_LIST(n,TL_SEQ_ONE_TYPELIST),\
NullType REPEAT(n,TL_SEQ_TL_END); \
}
LIST(TL_MAX_SEQ_SPECS,TL_SEQ_SPEC,;);
#undef TL_SEQ_SPEC
#undef TL_SEQ_TL_END
#undef TL_SEQ_ONE_TYPELIST
#undef TL_SEQ_NULLTYPE_DEFAULT
#undef TL_SEQ_TYPE
#undef TL_MAX_SEQ_SPECS
//----------------------------------------------------------------------
// Various utility functions follow.
/// Length<List>::value is the number of types in the typelist.
template <typename List> struct Length { };
template <> struct Length<NullType> { enum { value = 0 }; };
template <typename T, typename U>
struct Length<Typelist<T, U> > { enum { value = 1 + Length<U>::value }; };
/// TypeAt<List, i>::Result is the ith type in List
template <typename List, unsigned index> struct TypeAt { };
template <class Head, class Tail>
struct TypeAt<Typelist<Head, Tail>, 0> {
using Result = Head;
};
template <class Head, class Tail, unsigned index>
struct TypeAt<Typelist<Head, Tail>, index> {
using Result = typename TypeAt<Tail, index-1>::Result;
};
/// TypeAtNonStrict<List,i,DefaultType>::Result is List[i] or DefaultType if out of range.
template <typename List, unsigned index, typename DefaultType = NullType>
struct TypeAtNonStrict {
using Result = DefaultType;
};
template <typename Head, typename Tail, typename DefaultType>
struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType> {
using Result = Head;
};
template <typename Head, typename Tail, unsigned index, typename DefaultType>
struct TypeAtNonStrict<Typelist<Head, Tail>, index, DefaultType> {
using Result = typename TypeAtNonStrict<Tail, index-1, DefaultType>::Result;
};
/// IndexOf<List,T>::value is the position of T in List, or -1 if not found.
template <typename List, typename T> struct IndexOf;
template <typename T>
struct IndexOf<NullType, T> { enum { value = -1 }; };
template <typename T, typename Tail>
struct IndexOf<Typelist<T, Tail>, T> { enum { value = 0 }; };
template <typename Head, typename Tail, typename T>
struct IndexOf<Typelist<Head, Tail>, T> {
private:
enum { iintail = IndexOf<Tail, T>::value };
public:
enum { value = (iintail == -1 ? -1 : 1+iintail) };
};
/// Appends a type or a typelist to another in Append<TList, T>::Result
template <typename List, typename T> struct Append;
template <> struct Append<NullType, NullType> { using Result = NullType; };
template <typename T> struct Append<NullType, T> {
using Result = Typelist<T,NullType>;
};
template <typename Head, typename Tail>
struct Append<NullType, Typelist<Head, Tail> > {
using Result = Typelist<Head, Tail>;
};
template <typename Head, typename Tail, typename T>
struct Append<Typelist<Head, Tail>, T> {
using Result = Typelist<Head, typename Append<Tail, T>::Result>;
};
// Erase<List, T>::Result contains List without the first T.
template <typename TList, typename T> struct Erase;
template <typename T>
struct Erase<NullType, T> { using Result = NullType; };
template <typename T, typename Tail>
struct Erase<Typelist<T, Tail>, T> { using Result = Tail; };
template <typename Head, typename Tail, typename T>
struct Erase<Typelist<Head, Tail>, T> {
using Result = Typelist<Head, typename Erase<Tail, T>::Result>;
};
// EraseAll<List, T>::Result contains List without any T.
template <typename List, typename T> struct EraseAll;
template <typename T>
struct EraseAll<NullType, T> { using Result = NullType; };
template <typename T, typename Tail>
struct EraseAll<Typelist<T, Tail>, T> {
using Result = typename EraseAll<Tail, T>::Result;
};
template <typename Head, typename Tail, typename T>
struct EraseAll<Typelist<Head, Tail>, T> {
using Result = Typelist<Head, typename EraseAll<Tail, T>::Result>;
};
/// Removes all duplicate types in a typelist
template <typename List> struct NoDuplicates;
template <> struct NoDuplicates<NullType> { using Result = NullType; };
template <typename Head, typename Tail>
struct NoDuplicates< Typelist<Head, Tail> > {
private:
using L1 = typename NoDuplicates<Tail>::Result;
using L2 = typename Erase<L1, Head>::Result;
public:
using Result = Typelist<Head, L2>;
};
// Replaces the first occurence of a type in a typelist, with another type
template <typename List, typename T, typename U> struct Replace;
template <typename T, typename U>
struct Replace<NullType, T, U> { using Result = NullType; };
template <typename T, typename Tail, typename U>
struct Replace<Typelist<T, Tail>, T, U> {
using Result = Typelist<U, Tail>;
};
template <typename Head, typename Tail, typename T, typename U>
struct Replace<Typelist<Head, Tail>, T, U> {
using Result = Typelist<Head, typename Replace<Tail, T, U>::Result>;
};
// Replaces all occurences of a type in a typelist, with another type
template <typename List, typename T, typename U> struct ReplaceAll;
template <typename T, typename U>
struct ReplaceAll<NullType, T, U> { using Result = NullType; };
template <typename T, typename Tail, typename U>
struct ReplaceAll<Typelist<T, Tail>, T, U> {
using Result = Typelist<U, typename ReplaceAll<Tail, T, U>::Result>;
};
template <typename Head, typename Tail, typename T, typename U>
struct ReplaceAll<Typelist<Head, Tail>, T, U> {
using Result = Typelist<Head, typename ReplaceAll<Tail, T, U>::Result>;
};
// Reverses a typelist
template <typename List> struct Reverse;
template <> struct Reverse<NullType> { using Result = NullType; };
template <typename Head, typename Tail>
struct Reverse< Typelist<Head, Tail> > {
using Result = typename Append<typename Reverse<Tail>::Result, Head>::Result;
};
// Finds the type in a typelist that is the most derived from a given type
template <typename List, typename T> struct MostDerived;
template <typename T> struct MostDerived<NullType, T> { using Result = T; };
template <typename Head, typename Tail, typename T>
struct MostDerived<Typelist<Head, Tail>, T> {
private:
using Candidate = typename MostDerived<Tail, T>::Result;
public:
using Result = typename Select<SuperSubclass<Candidate,Head>::value, Head, Candidate>::Result;
};
// Arranges the types in a typelist so that the most derived types appear first
template <typename List> struct DerivedToFront;
template <> struct DerivedToFront<NullType> { using Result = NullType; };
template <typename Head, typename Tail>
struct DerivedToFront< Typelist<Head, Tail> > {
private:
using TheMostDerived = typename MostDerived<Tail, Head>::Result;
using Temp = typename Replace<Tail, TheMostDerived, Head>::Result;
using L = typename DerivedToFront<Temp>::Result;
public:
using Result = Typelist<TheMostDerived, L>;
};
//----------------------------------------------------------------------
} // namespace tl
} // namespace tm
} // namespace ustl