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_foreach.h
Go to the documentation of this file.
1 /// @file meta_foreach.h
2 ///
3 /// Defines a compile-time equivalent of std::for_each.
4 ///
5 /// Parameterized processing function that iterates through the type container
6 /// recursively to visit each targeted element.
7 ///
8 /// The MIT License(MIT)
9 /// @copyright 2014 Paul M Watt
10 // ****************************************************************************
11 #ifndef META_FOREACH_H_INCLUDED
12 #define META_FOREACH_H_INCLUDED
13 // Includes *******************************************************************
14 #include <Pb/meta_fwd.h>
15 
16 namespace Hg
17 {
18 
19 namespace detail
20 {
21 
22 // ****************************************************************************
23 /// This parameterized construct is used to iterate through each type in the
24 /// specified type container.
25 ///
26 /// @param CurIndex [size_t] The starting index for processing the type container.
27 /// This value must be less than EndIndex otherwise a
28 /// compiler error will be generated.
29 /// @param EndIndex [size_t]The last index to be processed in the type container.
30 /// @param ContainerT [typename] A type container to process.
31 /// Each type entry within the specified range will be processed.
32 /// A compiler error will be generated if this parameter
33 /// is not a Type Container.
34 /// @param Function [typename] The user specified functor to use on each type.
35 ///
36 template <size_t CurIndex,
37  size_t EndIndex,
38  typename ContainerT,
39  typename Function>
41 {
42  static_assert((CurIndex <= EndIndex),
43  "The Current Index must be not be greater than the End Index");
44  static_assert(type_container<ContainerT>::value,
45  "ContainerT must be derived from \"container_trait\"");
46 
47 public:
48  // **************************************************************************
49  /// Initializes this helper constructor for applying the input Functor fn to
50  /// each type specified in the Type Container passed to the Functor.
51  ///
52  /// @param fn The functor that will be called for each type.
53  ///
54  ForEachTypeHelper(Function& fn)
55  : ftor(fn)
56  {
57  // No current operations.
58  }
59 
60  // **************************************************************************
61  /// The function that allows this structure to operate as a functor.
62  ///
63  void operator()()
64  {
65  process<CurIndex, EndIndex, ContainerT>();
66  }
67 
68 private:
69  // Private Data *************************************************************
70  Function& ftor; ///< Used-defined parameterized functor that
71  /// is processed on each type in the specified
72  /// range on the type container.
73 
74  // Private Methods **********************************************************
75  // **************************************************************************
76  /// Internal parameterized processing function that iterates through
77  /// the type container recursively to visit each targeted element.
78  ///
79  /// @tparam IndexT [size_t] The starting index for processing the type container.
80  /// @tparam LastT [size_t] The last index to be processed in the type container.
81  /// @tparam FormatT [typename] A type container to process.
82  /// Each type entry within the specified range will be processed.
83  ///
84  template <size_t IndexT,
85  size_t LastT,
86  typename FormatT>
87  void process()
88  {
89  // Extract the type at the current index specified for this instance
90  // of the process helper function, and call the user's functor.
91  typedef typename TypeAt<IndexT, FormatT>::type type_t;
92 
93 #ifdef _WIN32
94  ftor.operator() < IndexT,
95  type_t
96  >((type_t*)0);
97 #else
98  // GCC requires a hint to know this is a template call
99  ftor. template operator() < IndexT,
100  type_t
101  >((type_t*)0);
102 #endif
103 
104  // Perform a runtime check to terminate the recursive processing of
105  // the type container elements.
106  if (IndexT < LastT)
107  {
108  // The value_if template construct is used to prevent an element from
109  // being defined that exceeds the boundaries of the type container.
110  process<value_if<(IndexT < LastT),
111  size_t,
112  IndexT+1,
113  LastT>::value,
114  LastT,
115  FormatT>();
116  }
117  }
118 };
119 
120 } // namespace detail
121 
122 // ****************************************************************************
123 /// Meta-template implementation of for_each.
124 ///
125 /// Meta-template to perform a user specified action on every element in the
126 /// specified type ContainerT. This is the compile-time equivalent of the
127 /// **std::for_each** function.
128 ///
129 /// @tparam BeginIndex [size_t] The starting index for processing the type container.
130 /// This value must be less than EndIndex otherwise a
131 /// compiler error will be generated.
132 /// @tparam EndIndex [size_t]The last index to be processed in the type container.
133 /// @tparam ContainerT [typename] A type container to process.
134 /// Each type entry within the specified range will be processed.
135 /// A compiler error will be generated if this parameter
136 /// is not a Type Container.
137 /// @tparam Function [typename] The user specified functor to use on each type.
138 ///
139 /// @param fn A functor that will be called for each type entry in the
140 /// container passed to the forEach function.
141 ///
142 /// Since this function works on a template type, the functor
143 /// must support a parameterized functor that accepts one type.
144 ///
145 /// @return The input functor is returned to capture any changed state.
146 ///
147 template <size_t BeginIndex,
148  size_t EndIndex,
149  typename ContainerT,
150  typename Function>
151 Function& ForEachType(Function &fn)
152 {
153  static_assert (BeginIndex <= EndIndex,
154  "The Begin Index must not be greater than the End Index");
155  static_assert (type_container<ContainerT>::value,
156  "ContainerT must be derived from \"container_trait\"");
157  static_assert (length<ContainerT>::value > 0,
158  "ContainerT must contain more than 0 type entries.");
159 
160  // The helper template is required because this processing is performed
161  // on types at compile-time. Dynamic input variables are not permitted for
162  // parameterized function calls.
163  typedef detail::ForEachTypeHelper<BeginIndex,
164  EndIndex,
165  ContainerT,
166  Function> Handler;
167  Handler process(fn);
168  process();
169 
170  // Return the same functor passed into the ForEachType call similar to
171  // the std::for_each call.
172  return fn;
173 }
174 
175 } // namespace Hg
176 
177 #endif