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