Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
integer_sequence.h
1 /// @file meta/integer_sequence.h
2 ///
3 /// A parameterized integral sequence construct.
4 ///
5 /// The integer_sequence can be used to hold a sequence of numbers in a list.
6 /// Operations are provided to get the first element from the sequence and
7 /// the remainder of the sequence. With these two operations the entire
8 /// sequence can be traversed at compile-time.
9 ///
10 /// @note This header file must not be included directly and the
11 /// MACROS defined in this file should not be accessed
12 /// directly. Include and used the definitions from the file
13 /// **<alchemy.h>** instead.
14 ///
15 /// The MIT License(MIT)
16 /// @copyright 2014 Paul M Watt
17 // ****************************************************************************
18 #ifndef INTEGER_SEQUENCE_H_INCLUDED
19 #define INTEGER_SEQUENCE_H_INCLUDED
20 // Includes *******************************************************************
21 #include <Pb/meta_fwd.h>
22 #include <Pb/meta_macros.h>
23 
24 namespace Hg
25 {
26 
27 // Constants ******************************************************************
28 static const size_t npos = ~0;
29 
30 // Generic Integral Node ******************************************************
31 template <size_t H, typename T>
32 struct IntegralNode
33  : std::integral_constant<size_t, H>
34 {
35  typedef IntegralNode<H, T> type;
36  typedef size_t value_type;
37 
38  typedef size_t head;
39  typedef T tail;
40 };
41 
42 // ****************************************************************************
43 /// A parameterized type that is a sequence of integer values.
44 ///
45 /// ~~~{.cpp}
46 /// template < size_t T0, size_t T1 = 0, size_t T2 = 0, size_t T3 = 0,
47 /// size_t T4 = 0, size_t T5 = 0, size_t T6 = 0, size_t T7 = 0,
48 /// size_t T8 = 0, size_t T9 = 0, size_t T10 = 0, size_t T11 = 0,
49 /// size_t T12 = 0, size_t T13 = 0, size_t T14 = 0, size_t T15 = 0,
50 /// size_t T16 = 0, size_t T17 = 0, size_t T18 = 0, size_t T19 = 0,
51 /// size_t T20 = 0, size_t T21 = 0, size_t T22 = 0, size_t T23 = 0,
52 /// size_t T24 = 0, size_t T25 = 0, size_t T26 = 0, size_t T27 = 0,
53 /// size_t T28 = 0, size_t T29 = 0, size_t T30 = 0, size_t T31 = 0
54 /// >
55 /// struct integer_sequence
56 /// {
57 /// typedef IntegralNode<T1,
58 /// IntegralNode<T2,
59 /// IntegralNode<T3,
60 /// IntegralNode<T4,
61 /// IntegralNode<T5,
62 /// IntegralNode<T6,
63 /// IntegralNode<T7,
64 /// IntegralNode<T8,
65 /// IntegralNode<T9,
66 /// IntegralNode<T10,
67 /// IntegralNode<T11,
68 /// IntegralNode<T12,
69 /// IntegralNode<T13,
70 /// IntegralNode<T14,
71 /// IntegralNode<T15,
72 /// IntegralNode<T16,
73 /// IntegralNode<T17,
74 /// IntegralNode<T18,
75 /// IntegralNode<T19,
76 /// IntegralNode<T20,
77 /// IntegralNode<T21,
78 /// IntegralNode<T22,
79 /// IntegralNode<T23,
80 /// IntegralNode<T24,
81 /// IntegralNode<T25,
82 /// IntegralNode<T26,
83 /// IntegralNode<T27,
84 /// IntegralNode<T28,
85 /// IntegralNode<T29,
86 /// IntegralNode<T30,
87 /// IntegralNode<T31,
88 /// IntegralNode<T32, MT>
89 /// > > > > > > > > > > > > > > >
90 /// > > > > > > > > > > > > > > > > type;
91 /// };
92 /// ~~~
93 ///
94 template < size_t T0, size_t T1 = 0, size_t T2 = 0, size_t T3 = 0,
95  size_t T4 = 0, size_t T5 = 0, size_t T6 = 0, size_t T7 = 0,
96  size_t T8 = 0, size_t T9 = 0, size_t T10 = 0, size_t T11 = 0,
97  size_t T12 = 0, size_t T13 = 0, size_t T14 = 0, size_t T15 = 0,
98  size_t T16 = 0, size_t T17 = 0, size_t T18 = 0, size_t T19 = 0,
99  size_t T20 = 0, size_t T21 = 0, size_t T22 = 0, size_t T23 = 0,
100  size_t T24 = 0, size_t T25 = 0, size_t T26 = 0, size_t T27 = 0,
101  size_t T28 = 0, size_t T29 = 0, size_t T30 = 0, size_t T31 = 0
102  >
104 {
105  // This typedef and MACRO declaration results in the definition
106  // listed in the comments for this type.
107 
108  // This typedef and MACRO declaration results in the definition
109  // listed in the comments for this type.
110  // The DECLARE_INTEGER_SEQUENCE MACRO is an indirection because the generated
111  // code contains a comma.
112  #define DECLARE_INTEGER_SEQUENCE TMP_ARRAY_32(IntegralNode<T), MT TMP_REPEAT_32(>)
113  typedef DECLARE_INTEGER_SEQUENCE type;
114  typedef size_t value_type;
115  typedef MT tail;
116  static const size_t value = T0;
117  static const size_t count = 1;
118 };
119 
120 
121 #define META_INT_SEQUENCE_DEF(S) \
122 template <TMP_ARRAY_##S(size_t T)> \
123 struct integer_sequence<TMP_ARRAY_##S(T)> \
124 { \
125  typedef TMP_ARRAY_##S(IntegralNode<T), MT TMP_REPEAT_##S(>) type; \
126  typedef size_t value_type; \
127  typedef typename type::tail tail; \
128  static const size_t value = type::value; \
129  static const size_t count = S; \
130 }
131 
132 // Define specializations of this array from 1 to 31 elements *****************
133 META_INT_SEQUENCE_DEF(1);
134 META_INT_SEQUENCE_DEF(2);
135 META_INT_SEQUENCE_DEF(3);
136 META_INT_SEQUENCE_DEF(4);
137 META_INT_SEQUENCE_DEF(5);
138 META_INT_SEQUENCE_DEF(6);
139 META_INT_SEQUENCE_DEF(7);
140 META_INT_SEQUENCE_DEF(8);
141 META_INT_SEQUENCE_DEF(9);
142 META_INT_SEQUENCE_DEF(10);
143 META_INT_SEQUENCE_DEF(11);
144 META_INT_SEQUENCE_DEF(12);
145 META_INT_SEQUENCE_DEF(13);
146 META_INT_SEQUENCE_DEF(14);
147 META_INT_SEQUENCE_DEF(15);
148 META_INT_SEQUENCE_DEF(16);
149 META_INT_SEQUENCE_DEF(17);
150 META_INT_SEQUENCE_DEF(18);
151 META_INT_SEQUENCE_DEF(19);
152 META_INT_SEQUENCE_DEF(20);
153 META_INT_SEQUENCE_DEF(21);
154 META_INT_SEQUENCE_DEF(22);
155 META_INT_SEQUENCE_DEF(23);
156 META_INT_SEQUENCE_DEF(24);
157 META_INT_SEQUENCE_DEF(25);
158 META_INT_SEQUENCE_DEF(26);
159 META_INT_SEQUENCE_DEF(27);
160 META_INT_SEQUENCE_DEF(28);
161 META_INT_SEQUENCE_DEF(29);
162 META_INT_SEQUENCE_DEF(30);
163 META_INT_SEQUENCE_DEF(31);
164 
165 
166 // Undefining the declaration MACRO to prevent its further use. ****************
167 #undef META_INT_SEQUENCE_DEF
168 
169 // A few utility operations and specializations for the integer_sequence ******
170 // ***************************************************************************
171 template <typename SeqT>
172 struct Front
173  : std::integral_constant< size_t, SeqT::value>
174 { };
175 
176 // ***************************************************************************
177 template <>
178 struct Front< MT >
179  : std::integral_constant< size_t, 0>
180 { };
181 
182 // ***************************************************************************
183 template <typename SeqT>
184 struct PopFront
185 {
186  typedef typename SeqT::tail type;
187 };
188 
189 // ***************************************************************************
190 template <>
191 struct PopFront <MT>
192 {
193  typedef MT type;
194 };
195 
196 // ***************************************************************************
197 /// Safely extracts the last value in an integral sequence.
198 ///
199 template <typename SeqT>
200 struct TailValue
201  : Front <typename PopFront<SeqT>::type>
202 { };
203 
204 // ***************************************************************************
205 /// Specialization to TailValue for the MT type node.
206 ///
207 template <>
208 struct TailValue <MT>
209  : std::integral_constant<size_t, 0>
210 { };
211 
212 // ***************************************************************************
213 /// Compares the tail-type of the sequence and indicates if the type is empty.
214 ///
215 template <typename SeqT>
217  : std::integral_constant< bool,
218  empty_type < typename PopFront<SeqT>::type>::value
219  || 0 == TailValue<SeqT>::value
220  >
221 { };
222 
223 // ***************************************************************************
224 /// Specialization for an MT type sequence..
225 ///
226 template <>
227 struct IsTailEmpty <MT>
228  : std::true_type
229 {};
230 
231 // ***************************************************************************
232 /// Returns the Tail of an Integral Sequence.
233 /// This is similar to PopFront, however, as soon as a 0 is encountered,
234 /// MT will be returned, rather than the remainder of the list.
235 ///
236 template <typename SeqT>
237 struct GetTail
238 {
239  typedef typename PopFront<SeqT>::type type;
240 };
241 
242 // ***************************************************************************
243 /// Specialization of GetTail for the MT node type.
244 ///
245 template <>
246 struct GetTail<MT>
247 {
248  typedef MT type;
249 };
250 
251 // ***************************************************************************
252 /// Returns the value of the item at the specified index.
253 ///
254 template< typename SeqT,
255  size_t IdxT
256  >
257 struct at
258  : std::integral_constant< size_t,
259  at< typename GetTail<SeqT>::type,
260  IdxT - 1
261  >::value
262  >
263 { };
264 
265 // ***************************************************************************
266 /// Terminating case that returns the value at the specified index..
267 ///
268 template< typename SeqT >
269 struct at<SeqT, 0>
270  : std::integral_constant<size_t, Front<SeqT>::value>
271 { };
272 
273 // ***************************************************************************
274 /// Specialization that handles an MT sequence.
275 ///
276 template< size_t IdxT >
277 struct at<MT, IdxT>
278  : std::integral_constant<size_t, 0>
279 { };
280 
281 // ***************************************************************************
282 /// Specialization that handles an MT sequence.
283 ///
284 template<>
285 struct at<MT, 0>
286  : std::integral_constant<size_t, 0>
287 { };
288 
289 // ***************************************************************************
290 /// Reverses the order the nodes in an integral_node list.
291 ///
292 template< typename ToT,
293  typename FromT
294  >
296  : reverse_nodes < IntegralNode<Front<FromT>::value, ToT>,
297  typename GetTail<FromT>::type
298  >
299 { };
300 
301 // ***************************************************************************
302 /// A terminating case for reversal of an integral_node list
303 ///
304 template< typename ToT >
305 struct reverse_nodes<ToT, MT>
306 {
307  typedef ToT type;
308 };
309 
310 // ***************************************************************************
311 /// Reverses the order the values in an integral_sequence.
312 ///
313 template< typename SeqT >
314 struct reverse
315  : reverse_nodes<MT, typename SeqT::type>
316 { };
317 
318 // ***************************************************************************
319 /// Searches the integer_sequence for a value and returns the position.
320 /// If the value is not found, Hg::npos is returned.
321 ///
322 template< typename SeqT,
323  size_t ValueT
324  >
325 struct find
326  : std::integral_constant< size_t,
327  value_if< ValueT == Front<SeqT>::value,
328  size_t,
329  0,
330  find< typename GetTail<SeqT>::type,
331  ValueT
332  >::value + 1
333  >::value
334  >
335 { };
336 
337 // ***************************************************************************
338 /// Searches the integer_sequence for a value and returns the position.
339 /// If the value is not found, Hg::npos is returned.
340 ///
341 template< size_t ValueT >
342 struct find<MT, ValueT>
343  : std::integral_constant< size_t, Hg::npos >
344 { };
345 
346 // ***************************************************************************
347 /// Searches the integer_sequence and indicates of the specified value is found.
348 ///
349 template< typename SeqT,
350  size_t ValueT
351  >
352 struct contains
353  : std::integral_constant< bool,
354  find<SeqT, ValueT>::value != Hg::npos
355  >
356 { };
357 
358 
359 
360 } // namespace Hg
361 
362 
363 
364 #endif