Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
meta_util.h
1 /// @file meta/meta_util.h
2 ///
3 /// Template Meta-Programming Utility Definitions
4 ///
5 /// This file contains small object toolkit constructs useful for TMP
6 /// as well as basic Code Generation MACROS to simplify the
7 /// declaration and appearance of repetitive entries.
8 ///
9 /// Remember, these constructs are required to allow the compiler to
10 /// inspect and deduce values at compile-time. Otherwise many of these
11 /// constructs would appear to be over complicated to simply define
12 /// a value, such as a boolean true.
13 ///
14 /// For meta-programming constructs, the compile-time equivalent to a
15 /// runtime variable is a type. Therefore, many constructs that provide
16 /// calculations and behave like function calls are implemented as
17 /// new types, typically structs.
18 ///
19 /// Contains: instance_of Base class used to declare a type
20 /// type_equal Sets an internal ::value to true if two types are equal
21 /// value_if A ternary operation to select a value
22 /// one_or_zero Casts a boolean value to an integer 1 or 0
23 /// value_type_of Extracts the value_type of a data value.
24 ///
25 ///
26 /// @note: TAGGING: Deriving from a type that reports desired traits.
27 /// Tagging is an important technique in meta-template programming because
28 /// it simplifies the instantiation of more complex constructs and
29 /// encourages reuse.
30 ///
31 /// The MIT License(MIT)
32 /// @copyright 2014 Paul M Watt
33 // ****************************************************************************
34 #ifndef META_UTIL_H_INCLUDED
35 #define META_UTIL_H_INCLUDED
36 // Includes *******************************************************************
37 #include <Pb/compiler.h>
38 #include <type_traits>
39 #include <array>
40 #include <vector>
41 
42 namespace Hg
43 {
44 
45 // ****************************************************************************
46 /// A type to represent an MT type for defining type lists and type arrays.
47 ///
48 struct MT { };
49 
50 // ****************************************************************************
51 /// An alias that may be more readable.
52 ///
53 typedef MT empty;
54 
55 
56 // ****************************************************************************
57 /// A short alias for the 'unsigned char'.
58 ///
59 typedef unsigned char byte_t;
60 
61 // ****************************************************************************
62 /// Affirmative Type for use in SFINAE selection templates.
63 ///
64 template < typename T >
65 struct yes_t
66 { char buffer[2]; };
67 
68 // ****************************************************************************
69 /// Negative Type for use in SFINAE selection templates.
70 ///
71 typedef char no_t;
72 
73 // ****************************************************************************
74 /// This construct provides mechanism to declare and
75 /// initialize compile-time global constants.
76 ///
77 /// @note This template type is very inexpensive to instantiate for
78 /// the compiler. Therefore it is used extensively when possible.
79 ///
80 template <typename T>
82 {
83  typedef T type;
84 
85  // This constructor allows global constants to be declared and initialized.
86  instance_of(int = 0)
87  { }
88 };
89 
90 // ***************************************************************************
91 /// This construct provides the compile-time equivalent of
92 /// the ternary operator ?: for value selection.
93 ///
94 template <bool predicate, typename T, T trueValue, T falseValue>
95 struct value_if
96  : std::integral_constant<T, trueValue>
97 { };
98 
99 // ***************************************************************************
100 /// Specialization for the false condition of the value selector.
101 ///
102 template <typename T, T trueValue, T falseValue>
103 struct value_if<false, T, trueValue, falseValue>
104  : std::integral_constant<T, falseValue>
105 { };
106 
107 // ***************************************************************************
108 /// Casts a static const boolean to an int of one or a zero.
109 ///
110 template <bool Predicate>
112  : std::integral_constant<int, 1>
113 { };
114 
115 // ***************************************************************************
116 /// Specialization for the false condition of the bool selector.
117 ///
118 template <>
119 struct one_or_zero<false>
120  : std::integral_constant<int, 0>
121 { };
122 
123 // ***************************************************************************
124 /// Static Assertion Base Template to verify type constraints for an object.
125 ///
126 /// Privately inherit an object from this struct, and supply the compile-time
127 /// check that reduces to a boolean value as the specialization type.
128 /// This instance of the template will compile properly.
129 ///
130 template <bool T>
132 { };
133 
134 // ***************************************************************************
135 /// A false specialization for the type_check template.
136 /// This struct contains no definition to force a compiler error
137 /// if the input boolean type resolves to false.
138 ///
139 /// If a compiler error occurs, inspect the class that triggered
140 /// the compiler error. This error indicates that the type
141 /// passed in for the derived class does not meet criteria
142 /// established for proper functionality.
143 ///
144 template<>
145 struct type_check<false>;
146 
147 // ***************************************************************************
148 /// Compares types against the MT type.
149 ///
150 template <typename T>
152  : std::is_same<T, MT>
153 { };
154 
155 // Boolean Operations ********************************************************
156 // ***************************************************************************
157 /// Takes the logical not of the type.
158 /// The type passed in must have a static boolean value named "value".
159 ///
160 template <typename T>
161 struct Not
162  : std::integral_constant<bool, !T::value>
163 { };
164 
165 // ***************************************************************************
166 /// Takes the logical and of the two input types.
167 /// The types passed in must have a static boolean value named "value".
168 ///
169 template <typename T,
170  typename U>
171 struct And
172  : std::integral_constant<bool, T::value && U::value>
173 { };
174 
175 // ***************************************************************************
176 /// Takes the logical or of the input types.
177 /// The types passed in must have a static boolean value named "value".
178 ///
179 template <typename T,
180  typename U>
181 struct Or
182  : std::integral_constant<bool, T::value || U::value>
183 { };
184 
185 // Type tags for differentiating objects *************************************
186 // ***************************************************************************
187 /// Indicates the field or message has a fixed static size at compile-time.
188 ///
189 struct static_size_trait { };
190 
191 // ***************************************************************************
192 /// Indicates the field or message has a dynamic size determined at run-time.
193 ///
195 
196 // ***************************************************************************
197 /// fundamental_trait identifies fundamental integral types.
198 ///
201 { };
202 
203 // ***************************************************************************
204 /// packed_trait identifies fundamental integral types, that automatically
205 /// perform bit-shift and mask operations to simulate bit-fields.
206 ///
209 { };
210 
211 // ***************************************************************************
212 /// A container_trait describes any type that is not a fundamental type or
213 /// bitfield. These types facilitate more complex data structures.
214 ///
215 struct container_trait{ };
216 
217 
218 // ***************************************************************************
219 /// A nested type indicates that the data that is contained within,
220 /// possibly requires an internal inspection to facilitate correct behavior.
221 ///
223  : container_trait { };
224 
225 
226 // ***************************************************************************
227 /// Sequence types are a class of types that contain more than one element
228 /// of the same type in series.
229 ///
231  : nested_trait { };
232 
233 // ***************************************************************************
234 /// Indicates the fields format is undefined and will be determined by context.
235 ///
237  : sequence_trait { };
238 
239 // ***************************************************************************
240 /// A sequence type that represents a dynamically sized field.
241 ///
245 { };
246 
247 
248 // ***************************************************************************
249 /// A sequence type that has a fixed size.
250 ///
252  : sequence_trait
254 { };
255 
256 
257 // ***************************************************************************
258 /// Indicates the format of the vector data is undefined, opaque.
259 ///
261  : vector_trait
262  , opaque_trait
263 { };
264 
265 // ***************************************************************************
266 /// Indicates the format of the array data is undefined, opaque.
267 ///
269  : array_trait
270  , opaque_trait
271 { };
272 
273 
274 
275 // BitField Message Field Discriminators *************************************
276 // Objects derived from the packed_trait are considered bitlist containers.
277 template <typename T>
278 struct packed_value
279  : std::integral_constant< bool,
280  std::is_base_of<packed_trait, T>::value>
281 { };
282 
283 
284 // Type Container Discriminators *********************************************
285 // Objects derived from the container_trait are considered type containers.
286 template <typename T>
287 struct type_container
288  : std::integral_constant<bool,
289  std::is_base_of<container_trait, T>::value>
290 { };
291 
292 
293 // A specialization of the emtpy type because it acts as a teminator. ********
294 template<>
295 struct type_container<MT>
296  : std::integral_constant<bool, false>
297 { };
298 
299 
300 // Nested Value Discriminators ***********************************************
301 template <typename T>
302 struct nested_value
303  : std::integral_constant < bool,
304  type_container<T>::value && !packed_value<T>::value>
305 { };
306 
307 
308 // A specialization of the emtpy type because it acts as a teminator. ********
309 template<>
310 struct nested_value<MT>
311  : std::integral_constant<bool, false>
312 { };
313 
314 
315 // Variable Length Homogenous Containers are considered vector_values *******
316 // ***************************************************************************
317 /// Detect a std::vector type. This is the default false case.
318 ///
319 template< typename T >
321  : std::false_type
322 { };
323 
324 
325 // ***************************************************************************
326 /// Detect a std::vector type. This version identifies the std::vector.
327 /// T is the type the vector contains,
328 /// A is the allocator.
329 ///
330 template< typename T,
331  typename A
332  >
333 struct is_std_vector<std::vector<T,A> >
334  : std::true_type
335 { };
336 
337 // ***************************************************************************
338 template <typename T>
339 struct vector_value
340  : And < Or < std::is_base_of<vector_trait, T>,
341  is_std_vector<T>
342  >,
343  Not < std::is_base_of<array_trait, T> >
344  >
345 { };
346 
347 // ***************************************************************************
348 template<>
349 struct vector_value<MT>
350  : std::integral_constant<bool, false>
351 { };
352 
353 // Fixed Length Homogenous Containers are considered array_values ************
354 // ***************************************************************************
355 /// Detect a std::array type. This is the default false case.
356 ///
357 template< typename T >
359  : std::false_type
360 { };
361 
362 // ***************************************************************************
363 /// Detect a std::array type. This version identifies the std::array.
364 ///
365 template< typename T,
366  size_t N
367  >
368 struct is_std_array<std::array<T,N> >
369  : std::true_type
370 { };
371 
372 // ***************************************************************************
373 // Detect native array types.
374 template< typename T>
375 struct array_value
376  : And < Or < std::is_base_of<array_trait, T>,
377  is_std_array<T>
378  >,
379  Not < std::is_base_of<vector_trait, T> >
380  >
381 { };
382 
383 // Multi-variable types are containers of homogenous entries *****************
384 template <typename T>
385 struct sequence_value
386  : std::integral_constant< bool,
387  Or< typename std::is_base_of<sequence_trait, T>,
388  Or< vector_value<T>,
389  array_value<T>
390  >
391  >::value
392  >
393 { };
394 
395 // ***************************************************************************
396 template<>
397 struct sequence_value<MT>
398  : std::integral_constant<bool, false>
399 { };
400 
401 
402 // Reports if a data type is opaque ******************************************
403 // ***************************************************************************
404 /// Detect a sequence type that uses an unsigned char (byte_t).
405 ///
406 template< typename T >
407 struct is_opaque
408  : std::false_type
409 { };
410 
411 
412 // ***************************************************************************
413 /// Detect a std::vector opaque type.
414 /// A is the allocator.
415 ///
416 template< typename A >
417 struct is_opaque<std::vector<byte_t,A> >
418  : std::true_type
419 { };
420 
421 
422 // ***************************************************************************
423 /// Detect a std::array opaque type.
424 /// N is the number of entries.
425 ///
426 template< size_t N >
427 struct is_opaque<std::array<byte_t,N> >
428  : std::true_type
429 { };
430 
431 
432 // ***************************************************************************
433 /// Detect if the current value type is opaque.
434 ///
435 template< typename T >
437  : std::integral_constant< bool, is_opaque<T>::value >
438 { };
439 
440 
441 } // namespace Hg
442 
443 #endif