Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
auto_index.h
1 /// @file meta/auto_index_MACROS.h
2 ///
3 /// Provides a construct to auto-increment an index at compile-time.
4 ///
5 /// The MIT License(MIT)
6 /// @copyright 2014 Paul M Watt
7 // ****************************************************************************
8 #ifndef AUTO_INDEX_H_INCLUDED
9 #define AUTO_INDEX_H_INCLUDED
10 // Includes *******************************************************************
11 #include <Pb/meta_util.h>
12 
13 namespace Hg
14 {
15 
16 #define HAS_COUNTER
17 #if defined(HAS_COUNTER)
18 
19 // ****************************************************************************
20 // This version is not portable because it depends upon the __COUNTER__ macro.
21 // However, until a more portable implementation for the version above can
22 // be implemented, this version is simple, and works for many compilers.
23 //
24 
25 // ****************************************************************************
26 #define BEGIN_COUNTER static const size_t k_enum_base = __COUNTER__ + 1;
27 
28 // ****************************************************************************
29 #define INC_COUNTER
30 
31 // ****************************************************************************
32 #define COUNTER_VALUE (__COUNTER__ - k_enum_base)
33 
34 // ****************************************************************************
35 #define END_ENUM
36 
37 #elif defined(_WIN32)
38 
39  // **************************************************************************
40  // It turns out that the way this implementation is integrated with the
41  // Hg objects is not portable because the standard does not allow template
42  // specialization to occur within a class scope.
43  //
44  // This version will still be used for WIN32 builds.
45  // The __COUNTER__ MACRO will be used for other compilers that support it.
46  // When a compiler is encountered that does not support either possibility,
47  // this issue will be revisited.
48  //
49 
50  // Forward Declarations *****************************************************
51 #define FORWARD_DECLARE_AUTO_INDEX \
52  template <int L> \
53  struct decrement_until_match;
54 
55  // **************************************************************************
56 #define ENUM_BEGIN \
57  template<int N> \
58  struct enum_begin \
59  : std::integral_constant<int, N> \
60  { };
61 
62  // **************************************************************************
63 #define ENUM_ENTRY_INVALID \
64  template<int N, bool IsValidT = false> \
65  struct enum_entry \
66  : std::integral_constant<bool, IsValidT> \
67  { };
68 
69  // **************************************************************************
70 #define ENUM_ENTRY_VALID \
71  template<int N> \
72  struct enum_entry<N, true> \
73  : std::true_type \
74  {};
75 
76  // **************************************************************************
77 #define ENUM_ENTRY_ZERO \
78  template<> \
79  struct enum_entry<0, true> \
80  : std::true_type \
81  {};
82 
83  // **************************************************************************
84 #define AUTO_INDEX_BEFORE \
85  template <int L> \
86  struct index_before \
87  : std::integral_constant< int, \
88  decrement_until_match<L - 1>::value \
89  > \
90  { };
91 
92  // **************************************************************************
93 #define AUTO_INDEX_NEXT \
94  template <int L> \
95  struct auto_index \
96  : std::integral_constant< int, index_before<L>::value + 1 > \
97  { };
98 
99  // **************************************************************************
100 #define AUTO_INDEX_ZERO \
101  template <> \
102  struct auto_index<0> \
103  : std::integral_constant< int, -1> \
104  { };
105 
106  // **************************************************************************
107 #define DECREMENT_UNTIL_MATCH \
108  template <int L> \
109  struct decrement_until_match \
110  : std::integral_constant< int, \
111  value_if< enum_entry<L>::value, \
112  int, \
113  auto_index<L>::value, \
114  decrement_until_match<L - 1>::value \
115  >::value \
116  > \
117  { };
118 
119  // **************************************************************************
120 #define DECREMENT_UNTIL_ZERO \
121  template <> \
122  struct decrement_until_match<0> \
123  : std::integral_constant <int, -1> \
124  { };
125 
126  // **************************************************************************
127 #define ADD_ENUM_H(ID) \
128  template<> \
129  struct enum_entry<(ID)> \
130  : std::true_type \
131  { };
132 
133 
134  // **************************************************************************
135 #define BEGIN_COUNTER \
136  FORWARD_DECLARE_AUTO_INDEX \
137  ENUM_BEGIN \
138  ENUM_ENTRY_INVALID \
139  ENUM_ENTRY_VALID \
140  ENUM_ENTRY_ZERO \
141  AUTO_INDEX_BEFORE \
142  AUTO_INDEX_NEXT \
143  AUTO_INDEX_ZERO \
144  DECREMENT_UNTIL_MATCH \
145  DECREMENT_UNTIL_ZERO \
146  typedef std::integral_constant<int, __LINE__> enum_base;
147 
148 // ****************************************************************************
149 #define INC_COUNTER ADD_ENUM_H(__LINE__ - enum_base::value)
150 
151 // ****************************************************************************
152 #define COUNTER_VALUE (auto_index<__LINE__- enum_base::value>::value)
153 
154 // ****************************************************************************
155 #define END_ENUM
156 
157 #else
158 
159 #error "An auto-incrementing index is not available for this compiler. Manual index items will be required."
160 
161 #endif
162 
163 
164 } // namespace Hg
165 
166 #endif
167