TorchCraftAI
A bot for machine learning research on StarCraft: Brood War
enum.h
1 // This file is part of Better Enums, released under the BSD 2-clause license.
2 // See doc/LICENSE for details, or visit http://github.com/aantron/better-enums.
3 
4 #pragma once
5 
6 #ifndef BETTER_ENUMS_ENUM_H
7 #define BETTER_ENUMS_ENUM_H
8 
9 
10 
11 #include <cstddef>
12 #include <cstring>
13 #include <iosfwd>
14 #include <stdexcept>
15 
16 
17 
18 // Feature detection.
19 
20 #ifdef __GNUC__
21 # ifdef __clang__
22 # if __has_feature(cxx_constexpr)
23 # define BETTER_ENUMS_HAVE_CONSTEXPR
24 # endif
25 # if !defined(__EXCEPTIONS) || !__has_feature(cxx_exceptions)
26 # define BETTER_ENUMS_NO_EXCEPTIONS
27 # endif
28 # else
29 # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
30 # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
31 # define BETTER_ENUMS_HAVE_CONSTEXPR
32 # endif
33 # endif
34 # ifndef __EXCEPTIONS
35 # define BETTER_ENUMS_NO_EXCEPTIONS
36 # endif
37 # endif
38 #endif
39 
40 #ifdef _MSC_VER
41 # ifdef __clang__
42 # if __has_feature(cxx_constexpr)
43 # define BETTER_ENUMS_HAVE_CONSTEXPR
44 # endif
45 # endif
46 # ifndef _CPPUNWIND
47 # define BETTER_ENUMS_NO_EXCEPTIONS
48 # endif
49 # if _MSC_VER < 1600
50 # define BETTER_ENUMS_VC2008_WORKAROUNDS
51 # endif
52 #endif
53 
54 #ifdef BETTER_ENUMS_CONSTEXPR
55 # define BETTER_ENUMS_HAVE_CONSTEXPR
56 #endif
57 
58 #ifdef BETTER_ENUMS_NO_CONSTEXPR
59 # ifdef BETTER_ENUMS_HAVE_CONSTEXPR
60 # undef BETTER_ENUMS_HAVE_CONSTEXPR
61 # endif
62 #endif
63 
64 // GCC (and maybe clang) can be made to warn about using 0 or NULL when nullptr
65 // is available, so Better Enums tries to use nullptr. This passage uses
66 // availability of constexpr as a proxy for availability of nullptr, i.e. it
67 // assumes that nullptr is available when compiling on the right versions of gcc
68 // and clang with the right -std flag. This is actually slightly wrong, because
69 // nullptr is also available in Visual C++, but constexpr isn't. This
70 // imprecision doesn't matter, however, because VC++ doesn't have the warnings
71 // that make using nullptr necessary.
72 #ifdef BETTER_ENUMS_HAVE_CONSTEXPR
73 # define BETTER_ENUMS_CONSTEXPR_ constexpr
74 # define BETTER_ENUMS_NULLPTR nullptr
75 #else
76 # define BETTER_ENUMS_CONSTEXPR_
77 # define BETTER_ENUMS_NULLPTR NULL
78 #endif
79 
80 #ifndef BETTER_ENUMS_NO_EXCEPTIONS
81 # define BETTER_ENUMS_IF_EXCEPTIONS(x) x
82 #else
83 # define BETTER_ENUMS_IF_EXCEPTIONS(x)
84 #endif
85 
86 #ifdef __GNUC__
87 # define BETTER_ENUMS_UNUSED __attribute__((__unused__))
88 #else
89 # define BETTER_ENUMS_UNUSED
90 #endif
91 
92 
93 
94 // Higher-order preprocessor macros.
95 
96 #ifdef BETTER_ENUMS_MACRO_FILE
97 # include BETTER_ENUMS_MACRO_FILE
98 #else
99 
100 #define BETTER_ENUMS_PP_MAP(macro, data, ...) \
101  BETTER_ENUMS_ID( \
102  BETTER_ENUMS_APPLY( \
103  BETTER_ENUMS_PP_MAP_VAR_COUNT, \
104  BETTER_ENUMS_PP_COUNT(__VA_ARGS__)) \
105  (macro, data, __VA_ARGS__))
106 
107 #define BETTER_ENUMS_PP_MAP_VAR_COUNT(count) BETTER_ENUMS_M ## count
108 
109 #define BETTER_ENUMS_APPLY(macro, ...) BETTER_ENUMS_ID(macro(__VA_ARGS__))
110 
111 #define BETTER_ENUMS_ID(x) x
112 
113 #define BETTER_ENUMS_M1(m, d, x) m(d,0,x)
114 #define BETTER_ENUMS_M2(m,d,x,...) m(d,1,x) \
115  BETTER_ENUMS_ID(BETTER_ENUMS_M1(m,d,__VA_ARGS__))
116 #define BETTER_ENUMS_M3(m,d,x,...) m(d,2,x) \
117  BETTER_ENUMS_ID(BETTER_ENUMS_M2(m,d,__VA_ARGS__))
118 #define BETTER_ENUMS_M4(m,d,x,...) m(d,3,x) \
119  BETTER_ENUMS_ID(BETTER_ENUMS_M3(m,d,__VA_ARGS__))
120 #define BETTER_ENUMS_M5(m,d,x,...) m(d,4,x) \
121  BETTER_ENUMS_ID(BETTER_ENUMS_M4(m,d,__VA_ARGS__))
122 #define BETTER_ENUMS_M6(m,d,x,...) m(d,5,x) \
123  BETTER_ENUMS_ID(BETTER_ENUMS_M5(m,d,__VA_ARGS__))
124 #define BETTER_ENUMS_M7(m,d,x,...) m(d,6,x) \
125  BETTER_ENUMS_ID(BETTER_ENUMS_M6(m,d,__VA_ARGS__))
126 #define BETTER_ENUMS_M8(m,d,x,...) m(d,7,x) \
127  BETTER_ENUMS_ID(BETTER_ENUMS_M7(m,d,__VA_ARGS__))
128 #define BETTER_ENUMS_M9(m,d,x,...) m(d,8,x) \
129  BETTER_ENUMS_ID(BETTER_ENUMS_M8(m,d,__VA_ARGS__))
130 #define BETTER_ENUMS_M10(m,d,x,...) m(d,9,x) \
131  BETTER_ENUMS_ID(BETTER_ENUMS_M9(m,d,__VA_ARGS__))
132 #define BETTER_ENUMS_M11(m,d,x,...) m(d,10,x) \
133  BETTER_ENUMS_ID(BETTER_ENUMS_M10(m,d,__VA_ARGS__))
134 #define BETTER_ENUMS_M12(m,d,x,...) m(d,11,x) \
135  BETTER_ENUMS_ID(BETTER_ENUMS_M11(m,d,__VA_ARGS__))
136 #define BETTER_ENUMS_M13(m,d,x,...) m(d,12,x) \
137  BETTER_ENUMS_ID(BETTER_ENUMS_M12(m,d,__VA_ARGS__))
138 #define BETTER_ENUMS_M14(m,d,x,...) m(d,13,x) \
139  BETTER_ENUMS_ID(BETTER_ENUMS_M13(m,d,__VA_ARGS__))
140 #define BETTER_ENUMS_M15(m,d,x,...) m(d,14,x) \
141  BETTER_ENUMS_ID(BETTER_ENUMS_M14(m,d,__VA_ARGS__))
142 #define BETTER_ENUMS_M16(m,d,x,...) m(d,15,x) \
143  BETTER_ENUMS_ID(BETTER_ENUMS_M15(m,d,__VA_ARGS__))
144 #define BETTER_ENUMS_M17(m,d,x,...) m(d,16,x) \
145  BETTER_ENUMS_ID(BETTER_ENUMS_M16(m,d,__VA_ARGS__))
146 #define BETTER_ENUMS_M18(m,d,x,...) m(d,17,x) \
147  BETTER_ENUMS_ID(BETTER_ENUMS_M17(m,d,__VA_ARGS__))
148 #define BETTER_ENUMS_M19(m,d,x,...) m(d,18,x) \
149  BETTER_ENUMS_ID(BETTER_ENUMS_M18(m,d,__VA_ARGS__))
150 #define BETTER_ENUMS_M20(m,d,x,...) m(d,19,x) \
151  BETTER_ENUMS_ID(BETTER_ENUMS_M19(m,d,__VA_ARGS__))
152 #define BETTER_ENUMS_M21(m,d,x,...) m(d,20,x) \
153  BETTER_ENUMS_ID(BETTER_ENUMS_M20(m,d,__VA_ARGS__))
154 #define BETTER_ENUMS_M22(m,d,x,...) m(d,21,x) \
155  BETTER_ENUMS_ID(BETTER_ENUMS_M21(m,d,__VA_ARGS__))
156 #define BETTER_ENUMS_M23(m,d,x,...) m(d,22,x) \
157  BETTER_ENUMS_ID(BETTER_ENUMS_M22(m,d,__VA_ARGS__))
158 #define BETTER_ENUMS_M24(m,d,x,...) m(d,23,x) \
159  BETTER_ENUMS_ID(BETTER_ENUMS_M23(m,d,__VA_ARGS__))
160 #define BETTER_ENUMS_M25(m,d,x,...) m(d,24,x) \
161  BETTER_ENUMS_ID(BETTER_ENUMS_M24(m,d,__VA_ARGS__))
162 #define BETTER_ENUMS_M26(m,d,x,...) m(d,25,x) \
163  BETTER_ENUMS_ID(BETTER_ENUMS_M25(m,d,__VA_ARGS__))
164 #define BETTER_ENUMS_M27(m,d,x,...) m(d,26,x) \
165  BETTER_ENUMS_ID(BETTER_ENUMS_M26(m,d,__VA_ARGS__))
166 #define BETTER_ENUMS_M28(m,d,x,...) m(d,27,x) \
167  BETTER_ENUMS_ID(BETTER_ENUMS_M27(m,d,__VA_ARGS__))
168 #define BETTER_ENUMS_M29(m,d,x,...) m(d,28,x) \
169  BETTER_ENUMS_ID(BETTER_ENUMS_M28(m,d,__VA_ARGS__))
170 #define BETTER_ENUMS_M30(m,d,x,...) m(d,29,x) \
171  BETTER_ENUMS_ID(BETTER_ENUMS_M29(m,d,__VA_ARGS__))
172 #define BETTER_ENUMS_M31(m,d,x,...) m(d,30,x) \
173  BETTER_ENUMS_ID(BETTER_ENUMS_M30(m,d,__VA_ARGS__))
174 #define BETTER_ENUMS_M32(m,d,x,...) m(d,31,x) \
175  BETTER_ENUMS_ID(BETTER_ENUMS_M31(m,d,__VA_ARGS__))
176 #define BETTER_ENUMS_M33(m,d,x,...) m(d,32,x) \
177  BETTER_ENUMS_ID(BETTER_ENUMS_M32(m,d,__VA_ARGS__))
178 #define BETTER_ENUMS_M34(m,d,x,...) m(d,33,x) \
179  BETTER_ENUMS_ID(BETTER_ENUMS_M33(m,d,__VA_ARGS__))
180 #define BETTER_ENUMS_M35(m,d,x,...) m(d,34,x) \
181  BETTER_ENUMS_ID(BETTER_ENUMS_M34(m,d,__VA_ARGS__))
182 #define BETTER_ENUMS_M36(m,d,x,...) m(d,35,x) \
183  BETTER_ENUMS_ID(BETTER_ENUMS_M35(m,d,__VA_ARGS__))
184 #define BETTER_ENUMS_M37(m,d,x,...) m(d,36,x) \
185  BETTER_ENUMS_ID(BETTER_ENUMS_M36(m,d,__VA_ARGS__))
186 #define BETTER_ENUMS_M38(m,d,x,...) m(d,37,x) \
187  BETTER_ENUMS_ID(BETTER_ENUMS_M37(m,d,__VA_ARGS__))
188 #define BETTER_ENUMS_M39(m,d,x,...) m(d,38,x) \
189  BETTER_ENUMS_ID(BETTER_ENUMS_M38(m,d,__VA_ARGS__))
190 #define BETTER_ENUMS_M40(m,d,x,...) m(d,39,x) \
191  BETTER_ENUMS_ID(BETTER_ENUMS_M39(m,d,__VA_ARGS__))
192 #define BETTER_ENUMS_M41(m,d,x,...) m(d,40,x) \
193  BETTER_ENUMS_ID(BETTER_ENUMS_M40(m,d,__VA_ARGS__))
194 #define BETTER_ENUMS_M42(m,d,x,...) m(d,41,x) \
195  BETTER_ENUMS_ID(BETTER_ENUMS_M41(m,d,__VA_ARGS__))
196 #define BETTER_ENUMS_M43(m,d,x,...) m(d,42,x) \
197  BETTER_ENUMS_ID(BETTER_ENUMS_M42(m,d,__VA_ARGS__))
198 #define BETTER_ENUMS_M44(m,d,x,...) m(d,43,x) \
199  BETTER_ENUMS_ID(BETTER_ENUMS_M43(m,d,__VA_ARGS__))
200 #define BETTER_ENUMS_M45(m,d,x,...) m(d,44,x) \
201  BETTER_ENUMS_ID(BETTER_ENUMS_M44(m,d,__VA_ARGS__))
202 #define BETTER_ENUMS_M46(m,d,x,...) m(d,45,x) \
203  BETTER_ENUMS_ID(BETTER_ENUMS_M45(m,d,__VA_ARGS__))
204 #define BETTER_ENUMS_M47(m,d,x,...) m(d,46,x) \
205  BETTER_ENUMS_ID(BETTER_ENUMS_M46(m,d,__VA_ARGS__))
206 #define BETTER_ENUMS_M48(m,d,x,...) m(d,47,x) \
207  BETTER_ENUMS_ID(BETTER_ENUMS_M47(m,d,__VA_ARGS__))
208 #define BETTER_ENUMS_M49(m,d,x,...) m(d,48,x) \
209  BETTER_ENUMS_ID(BETTER_ENUMS_M48(m,d,__VA_ARGS__))
210 #define BETTER_ENUMS_M50(m,d,x,...) m(d,49,x) \
211  BETTER_ENUMS_ID(BETTER_ENUMS_M49(m,d,__VA_ARGS__))
212 #define BETTER_ENUMS_M51(m,d,x,...) m(d,50,x) \
213  BETTER_ENUMS_ID(BETTER_ENUMS_M50(m,d,__VA_ARGS__))
214 #define BETTER_ENUMS_M52(m,d,x,...) m(d,51,x) \
215  BETTER_ENUMS_ID(BETTER_ENUMS_M51(m,d,__VA_ARGS__))
216 #define BETTER_ENUMS_M53(m,d,x,...) m(d,52,x) \
217  BETTER_ENUMS_ID(BETTER_ENUMS_M52(m,d,__VA_ARGS__))
218 #define BETTER_ENUMS_M54(m,d,x,...) m(d,53,x) \
219  BETTER_ENUMS_ID(BETTER_ENUMS_M53(m,d,__VA_ARGS__))
220 #define BETTER_ENUMS_M55(m,d,x,...) m(d,54,x) \
221  BETTER_ENUMS_ID(BETTER_ENUMS_M54(m,d,__VA_ARGS__))
222 #define BETTER_ENUMS_M56(m,d,x,...) m(d,55,x) \
223  BETTER_ENUMS_ID(BETTER_ENUMS_M55(m,d,__VA_ARGS__))
224 #define BETTER_ENUMS_M57(m,d,x,...) m(d,56,x) \
225  BETTER_ENUMS_ID(BETTER_ENUMS_M56(m,d,__VA_ARGS__))
226 #define BETTER_ENUMS_M58(m,d,x,...) m(d,57,x) \
227  BETTER_ENUMS_ID(BETTER_ENUMS_M57(m,d,__VA_ARGS__))
228 #define BETTER_ENUMS_M59(m,d,x,...) m(d,58,x) \
229  BETTER_ENUMS_ID(BETTER_ENUMS_M58(m,d,__VA_ARGS__))
230 #define BETTER_ENUMS_M60(m,d,x,...) m(d,59,x) \
231  BETTER_ENUMS_ID(BETTER_ENUMS_M59(m,d,__VA_ARGS__))
232 #define BETTER_ENUMS_M61(m,d,x,...) m(d,60,x) \
233  BETTER_ENUMS_ID(BETTER_ENUMS_M60(m,d,__VA_ARGS__))
234 #define BETTER_ENUMS_M62(m,d,x,...) m(d,61,x) \
235  BETTER_ENUMS_ID(BETTER_ENUMS_M61(m,d,__VA_ARGS__))
236 #define BETTER_ENUMS_M63(m,d,x,...) m(d,62,x) \
237  BETTER_ENUMS_ID(BETTER_ENUMS_M62(m,d,__VA_ARGS__))
238 #define BETTER_ENUMS_M64(m,d,x,...) m(d,63,x) \
239  BETTER_ENUMS_ID(BETTER_ENUMS_M63(m,d,__VA_ARGS__))
240 
241 #define BETTER_ENUMS_PP_COUNT_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
242  _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \
243  _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
244  _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, \
245  _56, _57, _58, _59, _60, _61, _62, _63, _64, count, ...) count
246 
247 #define BETTER_ENUMS_PP_COUNT(...) \
248  BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60,\
249  59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42,\
250  41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24,\
251  23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, \
252  4, 3, 2, 1))
253 
254 #define BETTER_ENUMS_ITERATE(X, f, l) X(f, l, 0) X(f, l, 1) X(f, l, 2) \
255  X(f, l, 3) X(f, l, 4) X(f, l, 5) X(f, l, 6) X(f, l, 7) X(f, l, 8) \
256  X(f, l, 9) X(f, l, 10) X(f, l, 11) X(f, l, 12) X(f, l, 13) X(f, l, 14) \
257  X(f, l, 15) X(f, l, 16) X(f, l, 17) X(f, l, 18) X(f, l, 19) X(f, l, 20) \
258  X(f, l, 21) X(f, l, 22) X(f, l, 23)
259 
260 #endif // #ifdef BETTER_ENUMS_MACRO_FILE else case
261 
262 
263 
264 namespace better_enums {
265 
266 
267 // Optional type.
268 
269 template <typename T>
270 BETTER_ENUMS_CONSTEXPR_ inline T _default()
271 {
272  return static_cast<typename T::_enumerated>(0);
273 }
274 
275 template <>
276 BETTER_ENUMS_CONSTEXPR_ inline const char* _default<const char*>()
277 {
278  return BETTER_ENUMS_NULLPTR;
279 }
280 
281 template <>
282 BETTER_ENUMS_CONSTEXPR_ inline std::size_t _default<std::size_t>()
283 {
284  return 0;
285 }
286 
287 template <typename T>
288 struct optional {
289  BETTER_ENUMS_CONSTEXPR_ optional() :
290  _valid(false), _value(_default<T>()) { }
291 
292  BETTER_ENUMS_CONSTEXPR_ optional(T v) : _valid(true), _value(v) { }
293 
294  BETTER_ENUMS_CONSTEXPR_ const T& operator *() const { return _value; }
295  BETTER_ENUMS_CONSTEXPR_ const T* operator ->() const { return &_value; }
296 
297  BETTER_ENUMS_CONSTEXPR_ operator bool() const { return _valid; }
298 
299  BETTER_ENUMS_CONSTEXPR_ const T& value() const { return _value; }
300 
301  private:
302  bool _valid;
303  T _value;
304 };
305 
306 template <typename CastTo, typename Element>
307 BETTER_ENUMS_CONSTEXPR_ static optional<CastTo>
308 _map_index(const Element *array, optional<std::size_t> index)
309 {
310  return index ? static_cast<CastTo>(array[*index]) : optional<CastTo>();
311 }
312 
313 #ifdef BETTER_ENUMS_VC2008_WORKAROUNDS
314 
315 #define BETTER_ENUMS_OR_THROW \
316  if (!maybe) \
317  throw std::runtime_error(message); \
318  \
319  return *maybe;
320 
321 #else
322 
323 #define BETTER_ENUMS_OR_THROW \
324  return maybe ? *maybe : throw std::runtime_error(message);
325 
326 #endif
327 
328 BETTER_ENUMS_IF_EXCEPTIONS(
329 template <typename T>
330 BETTER_ENUMS_CONSTEXPR_ static T _or_throw(optional<T> maybe,
331  const char *message)
332 {
333  BETTER_ENUMS_OR_THROW
334 }
335 )
336 
337 template <typename T>
338 BETTER_ENUMS_CONSTEXPR_ static T* _or_null(optional<T*> maybe)
339 {
340  return maybe ? *maybe : BETTER_ENUMS_NULLPTR;
341 }
342 
343 
344 
345 // Functional sequencing. This is essentially a comma operator wrapped in a
346 // constexpr function. g++ 4.7 doesn't "accept" integral constants in the second
347 // position for the comma operator, and emits an external symbol, which then
348 // causes a linking error.
349 
350 template <typename T, typename U>
351 BETTER_ENUMS_CONSTEXPR_ U
352 continue_with(T ignored BETTER_ENUMS_UNUSED, U value) { return value; }
353 
354 
355 
356 // Values array declaration helper.
357 
358 template <typename EnumType>
359 struct _eat_assign {
360  explicit BETTER_ENUMS_CONSTEXPR_ _eat_assign(EnumType value) : _value(value)
361  { }
362 
363  template <typename Any>
364  BETTER_ENUMS_CONSTEXPR_ const _eat_assign&
365  operator =(Any dummy BETTER_ENUMS_UNUSED) const { return *this; }
366 
367  BETTER_ENUMS_CONSTEXPR_ operator EnumType () const { return _value; }
368 
369  private:
370  EnumType _value;
371 };
372 
373 
374 
375 // Iterables.
376 
377 template <typename Element>
378 struct _Iterable {
379  typedef const Element* iterator;
380 
381  BETTER_ENUMS_CONSTEXPR_ iterator begin() const { return iterator(_array); }
382  BETTER_ENUMS_CONSTEXPR_ iterator end() const
383  { return iterator(_array + _size); }
384  BETTER_ENUMS_CONSTEXPR_ std::size_t size() const { return _size; }
385  BETTER_ENUMS_CONSTEXPR_ const Element& operator [](std::size_t index) const
386  { return _array[index]; }
387 
388  BETTER_ENUMS_CONSTEXPR_ _Iterable(const Element *array, std::size_t s) :
389  _array(array), _size(s) { }
390 
391  private:
392  const Element * const _array;
393  const std::size_t _size;
394 };
395 
396 
397 
398 // String routines.
399 
400 BETTER_ENUMS_CONSTEXPR_ static const char *_name_enders = "= \t\n";
401 
402 BETTER_ENUMS_CONSTEXPR_ inline bool _ends_name(char c, std::size_t index = 0)
403 {
404  return
405  c == _name_enders[index] ? true :
406  _name_enders[index] == '\0' ? false :
407  _ends_name(c, index + 1);
408 }
409 
410 BETTER_ENUMS_CONSTEXPR_ inline bool _has_initializer(const char *s,
411  std::size_t index = 0)
412 {
413  return
414  s[index] == '\0' ? false :
415  s[index] == '=' ? true :
416  _has_initializer(s, index + 1);
417 }
418 
419 BETTER_ENUMS_CONSTEXPR_ inline std::size_t
420 _constant_length(const char *s, std::size_t index = 0)
421 {
422  return _ends_name(s[index]) ? index : _constant_length(s, index + 1);
423 }
424 
425 BETTER_ENUMS_CONSTEXPR_ inline char
426 _select(const char *from, std::size_t from_length, std::size_t index)
427 {
428  return index >= from_length ? '\0' : from[index];
429 }
430 
431 BETTER_ENUMS_CONSTEXPR_ inline char _to_lower_ascii(char c)
432 {
433  return c >= 0x41 && c <= 0x5A ? static_cast<char>(c + 0x20) : c;
434 }
435 
436 BETTER_ENUMS_CONSTEXPR_ inline bool _names_match(const char *stringizedName,
437  const char *referenceName,
438  std::size_t index = 0)
439 {
440  return
441  _ends_name(stringizedName[index]) ? referenceName[index] == '\0' :
442  referenceName[index] == '\0' ? false :
443  stringizedName[index] != referenceName[index] ? false :
444  _names_match(stringizedName, referenceName, index + 1);
445 }
446 
447 BETTER_ENUMS_CONSTEXPR_ inline bool
448 _names_match_nocase(const char *stringizedName, const char *referenceName,
449  std::size_t index = 0)
450 {
451  return
452  _ends_name(stringizedName[index]) ? referenceName[index] == '\0' :
453  referenceName[index] == '\0' ? false :
454  _to_lower_ascii(stringizedName[index]) !=
455  _to_lower_ascii(referenceName[index]) ? false :
456  _names_match_nocase(stringizedName, referenceName, index + 1);
457 }
458 
459 inline void _trim_names(const char * const *raw_names,
460  const char **trimmed_names,
461  char *storage, std::size_t count)
462 {
463  std::size_t offset = 0;
464 
465  for (std::size_t index = 0; index < count; ++index) {
466  trimmed_names[index] = storage + offset;
467 
468  std::size_t trimmed_length =
469  std::strcspn(raw_names[index], _name_enders);
470  storage[offset + trimmed_length] = '\0';
471 
472  std::size_t raw_length = std::strlen(raw_names[index]);
473  offset += raw_length + 1;
474  }
475 }
476 
477 
478 
479 // Eager initialization.
480 template <typename Enum>
481 struct _initialize_at_program_start {
482  _initialize_at_program_start() { Enum::initialize(); }
483 };
484 
485 } // namespace better_enums
486 
487 
488 
489 // Array generation macros.
490 
491 #define BETTER_ENUMS_EAT_ASSIGN_SINGLE(EnumType, index, expression) \
492  ((::better_enums::_eat_assign<EnumType>)EnumType::expression),
493 
494 #define BETTER_ENUMS_EAT_ASSIGN(EnumType, ...) \
495  BETTER_ENUMS_ID( \
496  BETTER_ENUMS_PP_MAP( \
497  BETTER_ENUMS_EAT_ASSIGN_SINGLE, EnumType, __VA_ARGS__))
498 
499 
500 
501 #ifdef BETTER_ENUMS_HAVE_CONSTEXPR
502 
503 
504 
505 #define BETTER_ENUMS_SELECT_SINGLE_CHARACTER(from, from_length, index) \
506  ::better_enums::_select(from, from_length, index),
507 
508 #define BETTER_ENUMS_SELECT_CHARACTERS(from, from_length) \
509  BETTER_ENUMS_ITERATE( \
510  BETTER_ENUMS_SELECT_SINGLE_CHARACTER, from, from_length)
511 
512 
513 
514 #define BETTER_ENUMS_TRIM_SINGLE_STRING(ignored, index, expression) \
515 constexpr std::size_t _length_ ## index = \
516  ::better_enums::_constant_length(#expression); \
517 constexpr const char _trimmed_ ## index [] = \
518  { BETTER_ENUMS_SELECT_CHARACTERS(#expression, _length_ ## index) }; \
519 constexpr const char *_final_ ## index = \
520  ::better_enums::_has_initializer(#expression) ? \
521  _trimmed_ ## index : #expression;
522 
523 #define BETTER_ENUMS_TRIM_STRINGS(...) \
524  BETTER_ENUMS_ID( \
525  BETTER_ENUMS_PP_MAP( \
526  BETTER_ENUMS_TRIM_SINGLE_STRING, ignored, __VA_ARGS__))
527 
528 
529 
530 #define BETTER_ENUMS_REFER_TO_SINGLE_STRING(ignored, index, expression) \
531  _final_ ## index,
532 
533 #define BETTER_ENUMS_REFER_TO_STRINGS(...) \
534  BETTER_ENUMS_ID( \
535  BETTER_ENUMS_PP_MAP( \
536  BETTER_ENUMS_REFER_TO_SINGLE_STRING, ignored, __VA_ARGS__))
537 
538 
539 
540 #endif // #ifdef BETTER_ENUMS_HAVE_CONSTEXPR
541 
542 
543 
544 #define BETTER_ENUMS_STRINGIZE_SINGLE(ignored, index, expression) #expression,
545 
546 #define BETTER_ENUMS_STRINGIZE(...) \
547  BETTER_ENUMS_ID( \
548  BETTER_ENUMS_PP_MAP( \
549  BETTER_ENUMS_STRINGIZE_SINGLE, ignored, __VA_ARGS__))
550 
551 #define BETTER_ENUMS_RESERVE_STORAGE_SINGLE(ignored, index, expression) \
552  #expression ","
553 
554 #define BETTER_ENUMS_RESERVE_STORAGE(...) \
555  BETTER_ENUMS_ID( \
556  BETTER_ENUMS_PP_MAP( \
557  BETTER_ENUMS_RESERVE_STORAGE_SINGLE, ignored, __VA_ARGS__))
558 
559 
560 
561 // The enums proper.
562 
563 #define BETTER_ENUMS_NS(EnumType) better_enums_data_ ## EnumType
564 
565 #ifdef BETTER_ENUMS_VC2008_WORKAROUNDS
566 
567 #define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) \
568  BETTER_ENUMS_CONSTEXPR_ Enum(const Enum &other) : \
569  _value(other._value) { }
570 
571 #else
572 
573 #define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum)
574 
575 #endif
576 
577 #define BETTER_ENUMS_TYPE(SetUnderlyingType, SwitchType, GenerateSwitchType, \
578  GenerateStrings, ToStringConstexpr, \
579  DeclareInitialize, DefineInitialize, CallInitialize, \
580  Enum, Underlying, ...) \
581  \
582 namespace better_enums_data_ ## Enum { \
583  \
584 BETTER_ENUMS_ID(GenerateSwitchType(Underlying, __VA_ARGS__)) \
585  \
586 } \
587  \
588 class Enum { \
589  private: \
590  typedef ::better_enums::optional<Enum> _optional; \
591  typedef ::better_enums::optional<std::size_t> _optional_index; \
592  \
593  public: \
594  typedef Underlying _integral; \
595  \
596  enum _enumerated SetUnderlyingType(Underlying) { __VA_ARGS__ }; \
597  \
598  BETTER_ENUMS_CONSTEXPR_ Enum(_enumerated value) : _value(value) { } \
599  \
600  BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) \
601  \
602  BETTER_ENUMS_CONSTEXPR_ operator SwitchType(Enum)() const \
603  { \
604  return SwitchType(Enum)(_value); \
605  } \
606  \
607  BETTER_ENUMS_CONSTEXPR_ _integral _to_integral() const; \
608  BETTER_ENUMS_IF_EXCEPTIONS( \
609  BETTER_ENUMS_CONSTEXPR_ static Enum _from_integral(_integral value); \
610  ) \
611  BETTER_ENUMS_CONSTEXPR_ static Enum \
612  _from_integral_unchecked(_integral value); \
613  BETTER_ENUMS_CONSTEXPR_ static _optional \
614  _from_integral_nothrow(_integral value); \
615  \
616  ToStringConstexpr const char* _to_string() const; \
617  BETTER_ENUMS_IF_EXCEPTIONS( \
618  BETTER_ENUMS_CONSTEXPR_ static Enum _from_string(const char *name); \
619  ) \
620  BETTER_ENUMS_CONSTEXPR_ static _optional \
621  _from_string_nothrow(const char *name); \
622  \
623  BETTER_ENUMS_IF_EXCEPTIONS( \
624  BETTER_ENUMS_CONSTEXPR_ static Enum _from_string_nocase(const char *name); \
625  ) \
626  BETTER_ENUMS_CONSTEXPR_ static _optional \
627  _from_string_nocase_nothrow(const char *name); \
628  \
629  BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(_integral value); \
630  BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(const char *name); \
631  BETTER_ENUMS_CONSTEXPR_ static bool _is_valid_nocase(const char *name); \
632  \
633  typedef ::better_enums::_Iterable<Enum> _value_iterable; \
634  typedef ::better_enums::_Iterable<const char*> _name_iterable; \
635  \
636  typedef _value_iterable::iterator _value_iterator; \
637  typedef _name_iterable::iterator _name_iterator; \
638  \
639  BETTER_ENUMS_CONSTEXPR_ static const std::size_t _size_constant = \
640  BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT(__VA_ARGS__)); \
641  BETTER_ENUMS_CONSTEXPR_ static std::size_t _size() \
642  { return _size_constant; } \
643  \
644  BETTER_ENUMS_CONSTEXPR_ static const char* _name(); \
645  BETTER_ENUMS_CONSTEXPR_ static _value_iterable _values(); \
646  ToStringConstexpr static _name_iterable _names(); \
647  \
648  _integral _value; \
649  \
650  BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \
651  \
652  private: \
653  explicit BETTER_ENUMS_CONSTEXPR_ Enum(const _integral &value) : \
654  _value(value) { } \
655  \
656  DeclareInitialize \
657  \
658  BETTER_ENUMS_CONSTEXPR_ static _optional_index \
659  _from_value_loop(_integral value, std::size_t index = 0); \
660  BETTER_ENUMS_CONSTEXPR_ static _optional_index \
661  _from_string_loop(const char *name, std::size_t index = 0); \
662  BETTER_ENUMS_CONSTEXPR_ static _optional_index \
663  _from_string_nocase_loop(const char *name, std::size_t index = 0); \
664  \
665  friend struct ::better_enums::_initialize_at_program_start<Enum>; \
666 }; \
667  \
668 namespace better_enums_data_ ## Enum { \
669  \
670 static ::better_enums::_initialize_at_program_start<Enum> \
671  _force_initialization; \
672  \
673 enum _PutNamesInThisScopeAlso { __VA_ARGS__ }; \
674  \
675 BETTER_ENUMS_CONSTEXPR_ const Enum _value_array[] = \
676  { BETTER_ENUMS_ID(BETTER_ENUMS_EAT_ASSIGN(Enum, __VA_ARGS__)) }; \
677  \
678 BETTER_ENUMS_ID(GenerateStrings(Enum, __VA_ARGS__)) \
679  \
680 } \
681  \
682 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
683 inline const Enum \
684 operator +(Enum::_enumerated enumerated) \
685 { \
686  return static_cast<Enum>(enumerated); \
687 } \
688  \
689 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \
690 Enum::_from_value_loop(Enum::_integral value, std::size_t index) \
691 { \
692  return \
693  index == _size() ? \
694  _optional_index() : \
695  BETTER_ENUMS_NS(Enum)::_value_array[index]._value == value ? \
696  _optional_index(index) : \
697  _from_value_loop(value, index + 1); \
698 } \
699  \
700 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \
701 Enum::_from_string_loop(const char *name, std::size_t index) \
702 { \
703  return \
704  index == _size() ? _optional_index() : \
705  ::better_enums::_names_match( \
706  BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ? \
707  _optional_index(index) : \
708  _from_string_loop(name, index + 1); \
709 } \
710  \
711 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \
712 Enum::_from_string_nocase_loop(const char *name, std::size_t index) \
713 { \
714  return \
715  index == _size() ? _optional_index() : \
716  ::better_enums::_names_match_nocase( \
717  BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ? \
718  _optional_index(index) : \
719  _from_string_nocase_loop(name, index + 1); \
720 } \
721  \
722 BETTER_ENUMS_CONSTEXPR_ inline Enum::_integral Enum::_to_integral() const \
723 { \
724  return _integral(_value); \
725 } \
726  \
727 BETTER_ENUMS_CONSTEXPR_ inline Enum \
728 Enum::_from_integral_unchecked(_integral value) \
729 { \
730  return static_cast<_enumerated>(value); \
731 } \
732  \
733 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
734 Enum::_from_integral_nothrow(_integral value) \
735 { \
736  return \
737  ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array, \
738  _from_value_loop(value)); \
739 } \
740  \
741 BETTER_ENUMS_IF_EXCEPTIONS( \
742 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_integral(_integral value) \
743 { \
744  return \
745  ::better_enums::_or_throw(_from_integral_nothrow(value), \
746  #Enum "::_from_integral: invalid argument"); \
747 } \
748 ) \
749  \
750 ToStringConstexpr inline const char* Enum::_to_string() const \
751 { \
752  return \
753  ::better_enums::_or_null( \
754  ::better_enums::_map_index<const char*>( \
755  BETTER_ENUMS_NS(Enum)::_name_array(), \
756  _from_value_loop(CallInitialize(_value)))); \
757 } \
758  \
759 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
760 Enum::_from_string_nothrow(const char *name) \
761 { \
762  return \
763  ::better_enums::_map_index<Enum>( \
764  BETTER_ENUMS_NS(Enum)::_value_array, _from_string_loop(name)); \
765 } \
766  \
767 BETTER_ENUMS_IF_EXCEPTIONS( \
768 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string(const char *name) \
769 { \
770  return \
771  ::better_enums::_or_throw(_from_string_nothrow(name), \
772  #Enum "::_from_string: invalid argument"); \
773 } \
774 ) \
775  \
776 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
777 Enum::_from_string_nocase_nothrow(const char *name) \
778 { \
779  return \
780  ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array, \
781  _from_string_nocase_loop(name)); \
782 } \
783  \
784 BETTER_ENUMS_IF_EXCEPTIONS( \
785 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string_nocase(const char *name)\
786 { \
787  return \
788  ::better_enums::_or_throw( \
789  _from_string_nocase_nothrow(name), \
790  #Enum "::_from_string_nocase: invalid argument"); \
791 } \
792 ) \
793  \
794 BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(_integral value) \
795 { \
796  return _from_value_loop(value); \
797 } \
798  \
799 BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(const char *name) \
800 { \
801  return _from_string_loop(name); \
802 } \
803  \
804 BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid_nocase(const char *name) \
805 { \
806  return _from_string_nocase_loop(name); \
807 } \
808  \
809 BETTER_ENUMS_CONSTEXPR_ inline const char* Enum::_name() \
810 { \
811  return #Enum; \
812 } \
813  \
814 BETTER_ENUMS_CONSTEXPR_ inline Enum::_value_iterable Enum::_values() \
815 { \
816  return _value_iterable(BETTER_ENUMS_NS(Enum)::_value_array, _size()); \
817 } \
818  \
819 ToStringConstexpr inline Enum::_name_iterable Enum::_names() \
820 { \
821  return \
822  _name_iterable(BETTER_ENUMS_NS(Enum)::_name_array(), \
823  CallInitialize(_size())); \
824 } \
825  \
826 DefineInitialize(Enum) \
827  \
828 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
829 inline bool operator ==(const Enum &a, const Enum &b) \
830  { return a._to_integral() == b._to_integral(); } \
831  \
832 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
833 inline bool operator !=(const Enum &a, const Enum &b) \
834  { return a._to_integral() != b._to_integral(); } \
835  \
836 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
837 inline bool operator <(const Enum &a, const Enum &b) \
838  { return a._to_integral() < b._to_integral(); } \
839  \
840 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
841 inline bool operator <=(const Enum &a, const Enum &b) \
842  { return a._to_integral() <= b._to_integral(); } \
843  \
844 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
845 inline bool operator >(const Enum &a, const Enum &b) \
846  { return a._to_integral() > b._to_integral(); } \
847  \
848 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
849 inline bool operator >=(const Enum &a, const Enum &b) \
850  { return a._to_integral() >= b._to_integral(); } \
851  \
852  \
853 template <typename Char, typename Traits> \
854 std::basic_ostream<Char, Traits>& \
855 operator <<(std::basic_ostream<Char, Traits>& stream, const Enum &value) \
856 { \
857  return stream << value._to_string(); \
858 } \
859  \
860 template <typename Char, typename Traits> \
861 std::basic_istream<Char, Traits>& \
862 operator >>(std::basic_istream<Char, Traits>& stream, Enum &value) \
863 { \
864  std::basic_string<Char, Traits> buffer; \
865  \
866  stream >> buffer; \
867  ::better_enums::optional<Enum> converted = \
868  Enum::_from_string_nothrow(buffer.c_str()); \
869  \
870  if (converted) \
871  value = *converted; \
872  else \
873  stream.setstate(std::basic_istream<Char, Traits>::failbit); \
874  \
875  return stream; \
876 }
877 
878 
879 
880 // Enum feature options.
881 
882 // C++98, C++11
883 #define BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying)
884 
885 // C++11
886 #define BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying) \
887  : Underlying
888 
889 // C++98, C++11
890 #define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE(Type) \
891  _enumerated
892 
893 // C++11
894 #define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE(Type) \
895  BETTER_ENUMS_NS(Type)::_EnumClassForSwitchStatements
896 
897 // C++98, C++11
898 #define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE(Underlying, ...)
899 
900 // C++11
901 #define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE(Underlying, ...) \
902  enum class _EnumClassForSwitchStatements : Underlying { __VA_ARGS__ };
903 
904 // C++98
905 #define BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS(Enum, ...) \
906  inline const char** _raw_names() \
907  { \
908  static const char *value[] = \
909  { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) }; \
910  return value; \
911  } \
912  \
913  inline char* _name_storage() \
914  { \
915  static char storage[] = \
916  BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__)); \
917  return storage; \
918  } \
919  \
920  inline const char** _name_array() \
921  { \
922  static const char *value[Enum::_size_constant]; \
923  return value; \
924  } \
925  \
926  inline bool& _initialized() \
927  { \
928  static bool value = false; \
929  return value; \
930  }
931 
932 // C++11 fast version
933 #define BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...) \
934  constexpr const char *_the_raw_names[] = \
935  { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) }; \
936  \
937  constexpr const char * const * _raw_names() \
938  { \
939  return _the_raw_names; \
940  } \
941  \
942  inline char* _name_storage() \
943  { \
944  static char storage[] = \
945  BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__)); \
946  return storage; \
947  } \
948  \
949  inline const char** _name_array() \
950  { \
951  static const char *value[Enum::_size_constant]; \
952  return value; \
953  } \
954  \
955  inline bool& _initialized() \
956  { \
957  static bool value = false; \
958  return value; \
959  }
960 
961 // C++11 slow all-constexpr version
962 #define BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...) \
963  BETTER_ENUMS_ID(BETTER_ENUMS_TRIM_STRINGS(__VA_ARGS__)) \
964  \
965  constexpr const char * const _the_name_array[] = \
966  { BETTER_ENUMS_ID(BETTER_ENUMS_REFER_TO_STRINGS(__VA_ARGS__)) }; \
967  \
968  constexpr const char * const * _name_array() \
969  { \
970  return _the_name_array; \
971  } \
972  \
973  constexpr const char * const * _raw_names() \
974  { \
975  return _the_name_array; \
976  }
977 
978 // C++98, C++11 fast version
979 #define BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD
980 
981 // C++11 slow all-constexpr version
982 #define BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD \
983  constexpr
984 
985 // C++98, C++11 fast version
986 #define BETTER_ENUMS_DO_DECLARE_INITIALIZE \
987  static int initialize();
988 
989 // C++11 slow all-constexpr version
990 #define BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE \
991  static int initialize() { return 0; }
992 
993 // C++98, C++11 fast version
994 #define BETTER_ENUMS_DO_DEFINE_INITIALIZE(Enum) \
995  inline int Enum::initialize() \
996  { \
997  if (BETTER_ENUMS_NS(Enum)::_initialized()) \
998  return 0; \
999  \
1000  ::better_enums::_trim_names(BETTER_ENUMS_NS(Enum)::_raw_names(), \
1001  BETTER_ENUMS_NS(Enum)::_name_array(), \
1002  BETTER_ENUMS_NS(Enum)::_name_storage(), \
1003  _size()); \
1004  \
1005  BETTER_ENUMS_NS(Enum)::_initialized() = true; \
1006  \
1007  return 0; \
1008  }
1009 
1010 // C++11 slow all-constexpr version
1011 #define BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE(Enum)
1012 
1013 // C++98, C++11 fast version
1014 #define BETTER_ENUMS_DO_CALL_INITIALIZE(value) \
1015  ::better_enums::continue_with(initialize(), value)
1016 
1017 // C++11 slow all-constexpr version
1018 #define BETTER_ENUMS_DO_NOT_CALL_INITIALIZE(value) \
1019  value
1020 
1021 
1022 
1023 // User feature selection.
1024 
1025 #ifdef BETTER_ENUMS_STRICT_CONVERSION
1026 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE \
1027  BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE
1028 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE \
1029  BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE
1030 #else
1031 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE \
1032  BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE
1033 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE \
1034  BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE
1035 #endif
1036 
1037 
1038 
1039 #ifndef BETTER_ENUMS_DEFAULT_CONSTRUCTOR
1040 # define BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \
1041  private: \
1042  Enum() : _value(0) { }
1043 #endif
1044 
1045 
1046 
1047 #ifdef BETTER_ENUMS_HAVE_CONSTEXPR
1048 
1049 #ifdef BETTER_ENUMS_CONSTEXPR_TO_STRING
1050 # define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS \
1051  BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS
1052 # define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD \
1053  BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD
1054 # define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE \
1055  BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE
1056 # define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE \
1057  BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE
1058 # define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE \
1059  BETTER_ENUMS_DO_NOT_CALL_INITIALIZE
1060 #else
1061 # define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS \
1062  BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS
1063 # define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD \
1064  BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD
1065 # define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE \
1066  BETTER_ENUMS_DO_DECLARE_INITIALIZE
1067 # define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE \
1068  BETTER_ENUMS_DO_DEFINE_INITIALIZE
1069 # define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE \
1070  BETTER_ENUMS_DO_CALL_INITIALIZE
1071 #endif
1072 
1073 
1074 
1075 // Top-level macros.
1076 
1077 #define BETTER_ENUM(Enum, Underlying, ...) \
1078  BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \
1079  BETTER_ENUMS_CXX11_UNDERLYING_TYPE, \
1080  BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \
1081  BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \
1082  BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS, \
1083  BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD, \
1084  BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE, \
1085  BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE, \
1086  BETTER_ENUMS_DEFAULT_CALL_INITIALIZE, \
1087  Enum, Underlying, __VA_ARGS__))
1088 
1089 #define SLOW_ENUM(Enum, Underlying, ...) \
1090  BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \
1091  BETTER_ENUMS_CXX11_UNDERLYING_TYPE, \
1092  BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \
1093  BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \
1094  BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS, \
1095  BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD, \
1096  BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE, \
1097  BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE, \
1098  BETTER_ENUMS_DO_NOT_CALL_INITIALIZE, \
1099  Enum, Underlying, __VA_ARGS__))
1100 
1101 #else
1102 
1103 #define BETTER_ENUM(Enum, Underlying, ...) \
1104  BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \
1105  BETTER_ENUMS_CXX98_UNDERLYING_TYPE, \
1106  BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \
1107  BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \
1108  BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS, \
1109  BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD, \
1110  BETTER_ENUMS_DO_DECLARE_INITIALIZE, \
1111  BETTER_ENUMS_DO_DEFINE_INITIALIZE, \
1112  BETTER_ENUMS_DO_CALL_INITIALIZE, \
1113  Enum, Underlying, __VA_ARGS__))
1114 
1115 #endif
1116 
1117 
1118 
1119 namespace better_enums {
1120 
1121 // Maps.
1122 
1123 template <typename T>
1124 struct map_compare {
1125  BETTER_ENUMS_CONSTEXPR_ static bool less(const T& a, const T& b)
1126  { return a < b; }
1127 };
1128 
1129 template <>
1130 struct map_compare<const char*> {
1131  BETTER_ENUMS_CONSTEXPR_ static bool less(const char *a, const char *b)
1132  { return less_loop(a, b); }
1133 
1134  private:
1135  BETTER_ENUMS_CONSTEXPR_ static bool
1136  less_loop(const char *a, const char *b, size_t index = 0)
1137  {
1138  return
1139  a[index] != b[index] ? a[index] < b[index] :
1140  a[index] == '\0' ? false :
1141  less_loop(a, b, index + 1);
1142  }
1143 };
1144 
1145 template <typename Enum, typename T, typename Compare = map_compare<T> >
1146 struct map {
1147  typedef T (*function)(Enum);
1148 
1149  BETTER_ENUMS_CONSTEXPR_ explicit map(function f) : _f(f) { }
1150 
1151  BETTER_ENUMS_CONSTEXPR_ T from_enum(Enum value) const { return _f(value); }
1152  BETTER_ENUMS_CONSTEXPR_ T operator [](Enum value) const
1153  { return _f(value); }
1154 
1155  BETTER_ENUMS_CONSTEXPR_ Enum to_enum(T value) const
1156  {
1157  return
1158  _or_throw(to_enum_nothrow(value), "map::to_enum: invalid argument");
1159  }
1160 
1161  BETTER_ENUMS_CONSTEXPR_ optional<Enum>
1162  to_enum_nothrow(T value, size_t index = 0) const
1163  {
1164  return
1165  index >= Enum::_size() ? optional<Enum>() :
1166  Compare::less(_f(Enum::_values()[index]), value) ||
1167  Compare::less(value, _f(Enum::_values()[index])) ?
1168  to_enum_nothrow(value, index + 1) :
1169  Enum::_values()[index];
1170  }
1171 
1172  private:
1173  const function _f;
1174 };
1175 
1176 template <typename Enum, typename T>
1177 BETTER_ENUMS_CONSTEXPR_ map<Enum, T> make_map(T (*f)(Enum))
1178 {
1179  return map<Enum, T>(f);
1180 }
1181 
1182 }
1183 
1184 #endif // #ifndef BETTER_ENUMS_ENUM_H
size_t size(std::string const &path)
Get the size of the file in bytes.
Definition: fsutils.cpp:475
Definition: enum.h:264