6#ifndef BETTER_ENUMS_ENUM_H
7#define BETTER_ENUMS_ENUM_H
10#include "colony_config.h"
13#ifdef USE_CPL_TYPE_BETTERENUM_EXTEND_128_32
14#define BETTER_ENUMS_MACRO_FILE <Cpl/Type/enum_macros_128_32_.h>
22#ifdef USE_CPL_TYPE_BETTERENUM_MIN_FOOTPRINT
23#ifndef BETTER_ENUMS_CONSTEXPR_TO_STRING
24#define BETTER_ENUMS_CONSTEXPR_TO_STRING
29#ifndef USE_CPL_TYPE_BETTERENUM_DISABLE_DEFAULT_CONSTRUCTOR
30#define BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \
36#ifndef DOXYGEN_WILL_SKIP_THIS
49# define BETTER_ENUMS_IGNORE_OLD_CAST_HEADER _Pragma("clang diagnostic push")
50# define BETTER_ENUMS_IGNORE_OLD_CAST_BEGIN _Pragma("clang diagnostic ignored \"-Wold-style-cast\"")
51# define BETTER_ENUMS_IGNORE_OLD_CAST_END _Pragma("clang diagnostic pop")
52# define BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER
53# define BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN
54# define BETTER_ENUMS_IGNORE_ATTRIBUTES_END
56# define BETTER_ENUMS_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
57# if BETTER_ENUMS_GCC_VERSION > 40400
58# define BETTER_ENUMS_IGNORE_OLD_CAST_HEADER _Pragma("GCC diagnostic push")
59# define BETTER_ENUMS_IGNORE_OLD_CAST_BEGIN _Pragma("GCC diagnostic ignored \"-Wold-style-cast\"")
60# define BETTER_ENUMS_IGNORE_OLD_CAST_END _Pragma("GCC diagnostic pop")
61# if (BETTER_ENUMS_GCC_VERSION >= 70300)
62# define BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER _Pragma("GCC diagnostic push")
63# define BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN _Pragma("GCC diagnostic ignored \"-Wattributes\"")
64# define BETTER_ENUMS_IGNORE_ATTRIBUTES_END _Pragma("GCC diagnostic pop")
66# define BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER
67# define BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN
68# define BETTER_ENUMS_IGNORE_ATTRIBUTES_END
71# define BETTER_ENUMS_IGNORE_OLD_CAST_HEADER
72# define BETTER_ENUMS_IGNORE_OLD_CAST_BEGIN
73# define BETTER_ENUMS_IGNORE_OLD_CAST_END
74# define BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER
75# define BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN
76# define BETTER_ENUMS_IGNORE_ATTRIBUTES_END
80# define BETTER_ENUMS_IGNORE_OLD_CAST_HEADER
81# define BETTER_ENUMS_IGNORE_OLD_CAST_BEGIN
82# define BETTER_ENUMS_IGNORE_OLD_CAST_END
83# define BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER
84# define BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN
85# define BETTER_ENUMS_IGNORE_ATTRIBUTES_END
92# if __has_feature(cxx_constexpr)
93# define BETTER_ENUMS_HAVE_CONSTEXPR
95# if !defined(__EXCEPTIONS) || !__has_feature(cxx_exceptions)
96# define BETTER_ENUMS_NO_EXCEPTIONS
99# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
100# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
101# define BETTER_ENUMS_HAVE_CONSTEXPR
105# define BETTER_ENUMS_NO_EXCEPTIONS
112# define BETTER_ENUMS_HAVE_CONSTEXPR
115# if __has_feature(cxx_constexpr)
116# define BETTER_ENUMS_HAVE_CONSTEXPR
120# define BETTER_ENUMS_NO_EXCEPTIONS
123# define BETTER_ENUMS_VC2008_WORKAROUNDS
127#ifdef BETTER_ENUMS_CONSTEXPR
128# define BETTER_ENUMS_HAVE_CONSTEXPR
131#ifdef BETTER_ENUMS_NO_CONSTEXPR
132# ifdef BETTER_ENUMS_HAVE_CONSTEXPR
133# undef BETTER_ENUMS_HAVE_CONSTEXPR
145#ifdef BETTER_ENUMS_HAVE_CONSTEXPR
146# define BETTER_ENUMS_CONSTEXPR_ constexpr
147# define BETTER_ENUMS_NULLPTR nullptr
149# define BETTER_ENUMS_CONSTEXPR_
150# define BETTER_ENUMS_NULLPTR NULL
153#ifndef BETTER_ENUMS_NO_EXCEPTIONS
154# define BETTER_ENUMS_IF_EXCEPTIONS(x) x
156# define BETTER_ENUMS_IF_EXCEPTIONS(x)
160# define BETTER_ENUMS_UNUSED __attribute__((__unused__))
162# define BETTER_ENUMS_UNUSED
169#ifdef BETTER_ENUMS_MACRO_FILE
170# include BETTER_ENUMS_MACRO_FILE
173#define BETTER_ENUMS_PP_MAP(macro, data, ...) \
175 BETTER_ENUMS_APPLY( \
176 BETTER_ENUMS_PP_MAP_VAR_COUNT, \
177 BETTER_ENUMS_PP_COUNT(__VA_ARGS__)) \
178 (macro, data, __VA_ARGS__))
180#define BETTER_ENUMS_PP_MAP_VAR_COUNT(count) BETTER_ENUMS_M ## count
182#define BETTER_ENUMS_APPLY(macro, ...) BETTER_ENUMS_ID(macro(__VA_ARGS__))
184#define BETTER_ENUMS_ID(x) x
186#define BETTER_ENUMS_M1(m, d, x) m(d,0,x)
187#define BETTER_ENUMS_M2(m,d,x,...) m(d,1,x) \
188 BETTER_ENUMS_ID(BETTER_ENUMS_M1(m,d,__VA_ARGS__))
189#define BETTER_ENUMS_M3(m,d,x,...) m(d,2,x) \
190 BETTER_ENUMS_ID(BETTER_ENUMS_M2(m,d,__VA_ARGS__))
191#define BETTER_ENUMS_M4(m,d,x,...) m(d,3,x) \
192 BETTER_ENUMS_ID(BETTER_ENUMS_M3(m,d,__VA_ARGS__))
193#define BETTER_ENUMS_M5(m,d,x,...) m(d,4,x) \
194 BETTER_ENUMS_ID(BETTER_ENUMS_M4(m,d,__VA_ARGS__))
195#define BETTER_ENUMS_M6(m,d,x,...) m(d,5,x) \
196 BETTER_ENUMS_ID(BETTER_ENUMS_M5(m,d,__VA_ARGS__))
197#define BETTER_ENUMS_M7(m,d,x,...) m(d,6,x) \
198 BETTER_ENUMS_ID(BETTER_ENUMS_M6(m,d,__VA_ARGS__))
199#define BETTER_ENUMS_M8(m,d,x,...) m(d,7,x) \
200 BETTER_ENUMS_ID(BETTER_ENUMS_M7(m,d,__VA_ARGS__))
201#define BETTER_ENUMS_M9(m,d,x,...) m(d,8,x) \
202 BETTER_ENUMS_ID(BETTER_ENUMS_M8(m,d,__VA_ARGS__))
203#define BETTER_ENUMS_M10(m,d,x,...) m(d,9,x) \
204 BETTER_ENUMS_ID(BETTER_ENUMS_M9(m,d,__VA_ARGS__))
205#define BETTER_ENUMS_M11(m,d,x,...) m(d,10,x) \
206 BETTER_ENUMS_ID(BETTER_ENUMS_M10(m,d,__VA_ARGS__))
207#define BETTER_ENUMS_M12(m,d,x,...) m(d,11,x) \
208 BETTER_ENUMS_ID(BETTER_ENUMS_M11(m,d,__VA_ARGS__))
209#define BETTER_ENUMS_M13(m,d,x,...) m(d,12,x) \
210 BETTER_ENUMS_ID(BETTER_ENUMS_M12(m,d,__VA_ARGS__))
211#define BETTER_ENUMS_M14(m,d,x,...) m(d,13,x) \
212 BETTER_ENUMS_ID(BETTER_ENUMS_M13(m,d,__VA_ARGS__))
213#define BETTER_ENUMS_M15(m,d,x,...) m(d,14,x) \
214 BETTER_ENUMS_ID(BETTER_ENUMS_M14(m,d,__VA_ARGS__))
215#define BETTER_ENUMS_M16(m,d,x,...) m(d,15,x) \
216 BETTER_ENUMS_ID(BETTER_ENUMS_M15(m,d,__VA_ARGS__))
217#define BETTER_ENUMS_M17(m,d,x,...) m(d,16,x) \
218 BETTER_ENUMS_ID(BETTER_ENUMS_M16(m,d,__VA_ARGS__))
219#define BETTER_ENUMS_M18(m,d,x,...) m(d,17,x) \
220 BETTER_ENUMS_ID(BETTER_ENUMS_M17(m,d,__VA_ARGS__))
221#define BETTER_ENUMS_M19(m,d,x,...) m(d,18,x) \
222 BETTER_ENUMS_ID(BETTER_ENUMS_M18(m,d,__VA_ARGS__))
223#define BETTER_ENUMS_M20(m,d,x,...) m(d,19,x) \
224 BETTER_ENUMS_ID(BETTER_ENUMS_M19(m,d,__VA_ARGS__))
225#define BETTER_ENUMS_M21(m,d,x,...) m(d,20,x) \
226 BETTER_ENUMS_ID(BETTER_ENUMS_M20(m,d,__VA_ARGS__))
227#define BETTER_ENUMS_M22(m,d,x,...) m(d,21,x) \
228 BETTER_ENUMS_ID(BETTER_ENUMS_M21(m,d,__VA_ARGS__))
229#define BETTER_ENUMS_M23(m,d,x,...) m(d,22,x) \
230 BETTER_ENUMS_ID(BETTER_ENUMS_M22(m,d,__VA_ARGS__))
231#define BETTER_ENUMS_M24(m,d,x,...) m(d,23,x) \
232 BETTER_ENUMS_ID(BETTER_ENUMS_M23(m,d,__VA_ARGS__))
233#define BETTER_ENUMS_M25(m,d,x,...) m(d,24,x) \
234 BETTER_ENUMS_ID(BETTER_ENUMS_M24(m,d,__VA_ARGS__))
235#define BETTER_ENUMS_M26(m,d,x,...) m(d,25,x) \
236 BETTER_ENUMS_ID(BETTER_ENUMS_M25(m,d,__VA_ARGS__))
237#define BETTER_ENUMS_M27(m,d,x,...) m(d,26,x) \
238 BETTER_ENUMS_ID(BETTER_ENUMS_M26(m,d,__VA_ARGS__))
239#define BETTER_ENUMS_M28(m,d,x,...) m(d,27,x) \
240 BETTER_ENUMS_ID(BETTER_ENUMS_M27(m,d,__VA_ARGS__))
241#define BETTER_ENUMS_M29(m,d,x,...) m(d,28,x) \
242 BETTER_ENUMS_ID(BETTER_ENUMS_M28(m,d,__VA_ARGS__))
243#define BETTER_ENUMS_M30(m,d,x,...) m(d,29,x) \
244 BETTER_ENUMS_ID(BETTER_ENUMS_M29(m,d,__VA_ARGS__))
245#define BETTER_ENUMS_M31(m,d,x,...) m(d,30,x) \
246 BETTER_ENUMS_ID(BETTER_ENUMS_M30(m,d,__VA_ARGS__))
247#define BETTER_ENUMS_M32(m,d,x,...) m(d,31,x) \
248 BETTER_ENUMS_ID(BETTER_ENUMS_M31(m,d,__VA_ARGS__))
249#define BETTER_ENUMS_M33(m,d,x,...) m(d,32,x) \
250 BETTER_ENUMS_ID(BETTER_ENUMS_M32(m,d,__VA_ARGS__))
251#define BETTER_ENUMS_M34(m,d,x,...) m(d,33,x) \
252 BETTER_ENUMS_ID(BETTER_ENUMS_M33(m,d,__VA_ARGS__))
253#define BETTER_ENUMS_M35(m,d,x,...) m(d,34,x) \
254 BETTER_ENUMS_ID(BETTER_ENUMS_M34(m,d,__VA_ARGS__))
255#define BETTER_ENUMS_M36(m,d,x,...) m(d,35,x) \
256 BETTER_ENUMS_ID(BETTER_ENUMS_M35(m,d,__VA_ARGS__))
257#define BETTER_ENUMS_M37(m,d,x,...) m(d,36,x) \
258 BETTER_ENUMS_ID(BETTER_ENUMS_M36(m,d,__VA_ARGS__))
259#define BETTER_ENUMS_M38(m,d,x,...) m(d,37,x) \
260 BETTER_ENUMS_ID(BETTER_ENUMS_M37(m,d,__VA_ARGS__))
261#define BETTER_ENUMS_M39(m,d,x,...) m(d,38,x) \
262 BETTER_ENUMS_ID(BETTER_ENUMS_M38(m,d,__VA_ARGS__))
263#define BETTER_ENUMS_M40(m,d,x,...) m(d,39,x) \
264 BETTER_ENUMS_ID(BETTER_ENUMS_M39(m,d,__VA_ARGS__))
265#define BETTER_ENUMS_M41(m,d,x,...) m(d,40,x) \
266 BETTER_ENUMS_ID(BETTER_ENUMS_M40(m,d,__VA_ARGS__))
267#define BETTER_ENUMS_M42(m,d,x,...) m(d,41,x) \
268 BETTER_ENUMS_ID(BETTER_ENUMS_M41(m,d,__VA_ARGS__))
269#define BETTER_ENUMS_M43(m,d,x,...) m(d,42,x) \
270 BETTER_ENUMS_ID(BETTER_ENUMS_M42(m,d,__VA_ARGS__))
271#define BETTER_ENUMS_M44(m,d,x,...) m(d,43,x) \
272 BETTER_ENUMS_ID(BETTER_ENUMS_M43(m,d,__VA_ARGS__))
273#define BETTER_ENUMS_M45(m,d,x,...) m(d,44,x) \
274 BETTER_ENUMS_ID(BETTER_ENUMS_M44(m,d,__VA_ARGS__))
275#define BETTER_ENUMS_M46(m,d,x,...) m(d,45,x) \
276 BETTER_ENUMS_ID(BETTER_ENUMS_M45(m,d,__VA_ARGS__))
277#define BETTER_ENUMS_M47(m,d,x,...) m(d,46,x) \
278 BETTER_ENUMS_ID(BETTER_ENUMS_M46(m,d,__VA_ARGS__))
279#define BETTER_ENUMS_M48(m,d,x,...) m(d,47,x) \
280 BETTER_ENUMS_ID(BETTER_ENUMS_M47(m,d,__VA_ARGS__))
281#define BETTER_ENUMS_M49(m,d,x,...) m(d,48,x) \
282 BETTER_ENUMS_ID(BETTER_ENUMS_M48(m,d,__VA_ARGS__))
283#define BETTER_ENUMS_M50(m,d,x,...) m(d,49,x) \
284 BETTER_ENUMS_ID(BETTER_ENUMS_M49(m,d,__VA_ARGS__))
285#define BETTER_ENUMS_M51(m,d,x,...) m(d,50,x) \
286 BETTER_ENUMS_ID(BETTER_ENUMS_M50(m,d,__VA_ARGS__))
287#define BETTER_ENUMS_M52(m,d,x,...) m(d,51,x) \
288 BETTER_ENUMS_ID(BETTER_ENUMS_M51(m,d,__VA_ARGS__))
289#define BETTER_ENUMS_M53(m,d,x,...) m(d,52,x) \
290 BETTER_ENUMS_ID(BETTER_ENUMS_M52(m,d,__VA_ARGS__))
291#define BETTER_ENUMS_M54(m,d,x,...) m(d,53,x) \
292 BETTER_ENUMS_ID(BETTER_ENUMS_M53(m,d,__VA_ARGS__))
293#define BETTER_ENUMS_M55(m,d,x,...) m(d,54,x) \
294 BETTER_ENUMS_ID(BETTER_ENUMS_M54(m,d,__VA_ARGS__))
295#define BETTER_ENUMS_M56(m,d,x,...) m(d,55,x) \
296 BETTER_ENUMS_ID(BETTER_ENUMS_M55(m,d,__VA_ARGS__))
297#define BETTER_ENUMS_M57(m,d,x,...) m(d,56,x) \
298 BETTER_ENUMS_ID(BETTER_ENUMS_M56(m,d,__VA_ARGS__))
299#define BETTER_ENUMS_M58(m,d,x,...) m(d,57,x) \
300 BETTER_ENUMS_ID(BETTER_ENUMS_M57(m,d,__VA_ARGS__))
301#define BETTER_ENUMS_M59(m,d,x,...) m(d,58,x) \
302 BETTER_ENUMS_ID(BETTER_ENUMS_M58(m,d,__VA_ARGS__))
303#define BETTER_ENUMS_M60(m,d,x,...) m(d,59,x) \
304 BETTER_ENUMS_ID(BETTER_ENUMS_M59(m,d,__VA_ARGS__))
305#define BETTER_ENUMS_M61(m,d,x,...) m(d,60,x) \
306 BETTER_ENUMS_ID(BETTER_ENUMS_M60(m,d,__VA_ARGS__))
307#define BETTER_ENUMS_M62(m,d,x,...) m(d,61,x) \
308 BETTER_ENUMS_ID(BETTER_ENUMS_M61(m,d,__VA_ARGS__))
309#define BETTER_ENUMS_M63(m,d,x,...) m(d,62,x) \
310 BETTER_ENUMS_ID(BETTER_ENUMS_M62(m,d,__VA_ARGS__))
311#define BETTER_ENUMS_M64(m,d,x,...) m(d,63,x) \
312 BETTER_ENUMS_ID(BETTER_ENUMS_M63(m,d,__VA_ARGS__))
314#define BETTER_ENUMS_PP_COUNT_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
315 _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \
316 _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
317 _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, \
318 _56, _57, _58, _59, _60, _61, _62, _63, _64, count, ...) count
320#define BETTER_ENUMS_PP_COUNT(...) \
321 BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60,\
322 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42,\
323 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24,\
324 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, \
327#define BETTER_ENUMS_ITERATE(X, f, l) X(f, l, 0) X(f, l, 1) X(f, l, 2) \
328 X(f, l, 3) X(f, l, 4) X(f, l, 5) X(f, l, 6) X(f, l, 7) X(f, l, 8) \
329 X(f, l, 9) X(f, l, 10) X(f, l, 11) X(f, l, 12) X(f, l, 13) X(f, l, 14) \
330 X(f, l, 15) X(f, l, 16) X(f, l, 17) X(f, l, 18) X(f, l, 19) X(f, l, 20) \
331 X(f, l, 21) X(f, l, 22) X(f, l, 23)
337namespace better_enums {
343BETTER_ENUMS_CONSTEXPR_
inline T _default()
345 return static_cast<typename T::_enumerated
>(0);
349BETTER_ENUMS_CONSTEXPR_
inline const char* _default<const char*>()
351 return BETTER_ENUMS_NULLPTR;
355BETTER_ENUMS_CONSTEXPR_
inline std::size_t _default<std::size_t>()
362 BETTER_ENUMS_CONSTEXPR_ optional() :
363 _valid( false ), _value( _default<T>() ) { }
365 BETTER_ENUMS_CONSTEXPR_ optional( T v ) : _valid( true ), _value( v ) { }
367 BETTER_ENUMS_CONSTEXPR_
const T& operator *()
const {
return _value; }
368 BETTER_ENUMS_CONSTEXPR_
const T* operator ->()
const {
return &_value; }
370 BETTER_ENUMS_CONSTEXPR_
operator bool()
const {
return _valid; }
372 BETTER_ENUMS_CONSTEXPR_
const T& value()
const {
return _value; }
379template <
typename CastTo,
typename Element>
380BETTER_ENUMS_CONSTEXPR_
static optional<CastTo>
381_map_index(
const Element *array, optional<std::size_t> index )
383 return index ?
static_cast<CastTo
>(array[*index]) : optional<CastTo>();
386#ifdef BETTER_ENUMS_VC2008_WORKAROUNDS
388#define BETTER_ENUMS_OR_THROW \
390 throw std::runtime_error(message); \
396#define BETTER_ENUMS_OR_THROW \
397 return maybe ? *maybe : throw std::runtime_error(message);
401BETTER_ENUMS_IF_EXCEPTIONS(
402 template <typename T>
403BETTER_ENUMS_CONSTEXPR_
static T _or_throw( optional<T> maybe,
404 const char *message )
406 BETTER_ENUMS_OR_THROW
411BETTER_ENUMS_CONSTEXPR_
static T* _or_null( optional<T*> maybe )
413 return maybe ? *maybe : BETTER_ENUMS_NULLPTR;
417BETTER_ENUMS_CONSTEXPR_
static T _or_zero( optional<T> maybe )
419 return maybe ? *maybe : T::_from_integral_unchecked( 0 );
429template <
typename T,
typename U>
430BETTER_ENUMS_CONSTEXPR_ U
431continue_with( T, U value ) {
return value; }
439template <
typename EnumType>
441 explicit BETTER_ENUMS_CONSTEXPR_ _eat_assign( EnumType value ) : _value( value )
444 template <
typename Any>
445 BETTER_ENUMS_CONSTEXPR_
const _eat_assign&
446 operator =( Any )
const {
return *
this; }
448 BETTER_ENUMS_CONSTEXPR_
operator EnumType ()
const {
return _value; }
458template <
typename Element>
460 typedef const Element* iterator;
462 BETTER_ENUMS_CONSTEXPR_ iterator begin()
const {
return iterator( _array ); }
463 BETTER_ENUMS_CONSTEXPR_ iterator end()
const
465 return iterator( _array + _size );
467 BETTER_ENUMS_CONSTEXPR_ std::size_t size()
const {
return _size; }
468 BETTER_ENUMS_CONSTEXPR_
const Element& operator []( std::size_t index )
const
470 return _array[index];
473 BETTER_ENUMS_CONSTEXPR_ _iterable(
const Element *array, std::size_t s ) :
474 _array( array ), _size( s ) { }
477 const Element *
const _array;
478 const std::size_t _size;
485BETTER_ENUMS_CONSTEXPR_
static const char *_name_enders =
"= \t\n";
487BETTER_ENUMS_CONSTEXPR_
inline bool _ends_name(
char c, std::size_t index = 0 )
490 c == _name_enders[index] ? true :
491 _name_enders[index] ==
'\0' ? false :
492 _ends_name( c, index + 1 );
495BETTER_ENUMS_CONSTEXPR_
inline bool _has_initializer(
const char *s,
496 std::size_t index = 0 )
499 s[index] ==
'\0' ? false :
500 s[index] ==
'=' ? true :
501 _has_initializer( s, index + 1 );
504BETTER_ENUMS_CONSTEXPR_
inline std::size_t
505_constant_length(
const char *s, std::size_t index = 0 )
507 return _ends_name( s[index] ) ? index : _constant_length( s, index + 1 );
510BETTER_ENUMS_CONSTEXPR_
inline char
511_select(
const char *from, std::size_t from_length, std::size_t index )
513 return index >= from_length ?
'\0' : from[index];
516BETTER_ENUMS_CONSTEXPR_
inline char _to_lower_ascii(
char c )
518 return c >= 0x41 && c <= 0x5A ? static_cast<char>(c + 0x20) : c;
521BETTER_ENUMS_CONSTEXPR_
inline bool _names_match(
const char *stringizedName,
522 const char *referenceName,
523 std::size_t index = 0 )
526 _ends_name( stringizedName[index] ) ? referenceName[index] ==
'\0' :
527 referenceName[index] ==
'\0' ? false :
528 stringizedName[index] != referenceName[index] ? false :
529 _names_match( stringizedName, referenceName, index + 1 );
532BETTER_ENUMS_CONSTEXPR_
inline bool
533_names_match_nocase(
const char *stringizedName,
const char *referenceName,
534 std::size_t index = 0 )
537 _ends_name( stringizedName[index] ) ? referenceName[index] ==
'\0' :
538 referenceName[index] ==
'\0' ? false :
539 _to_lower_ascii( stringizedName[index] ) !=
540 _to_lower_ascii( referenceName[index] ) ? false :
541 _names_match_nocase( stringizedName, referenceName, index + 1 );
544inline void _trim_names(
const char *
const *raw_names,
545 const char **trimmed_names,
546 char *storage, std::size_t count )
548 std::size_t offset = 0;
550 for ( std::size_t index = 0; index < count; ++index ) {
551 trimmed_names[index] = storage + offset;
553 std::size_t trimmed_length =
554 std::strcspn( raw_names[index], _name_enders );
555 storage[offset + trimmed_length] =
'\0';
557 std::size_t raw_length = std::strlen( raw_names[index] );
558 offset += raw_length + 1;
565template <
typename Enum>
566struct _initialize_at_program_start {
567 _initialize_at_program_start() { Enum::initialize(); }
576#define BETTER_ENUMS_EAT_ASSIGN_SINGLE(EnumType, index, expression) \
577 (EnumType)((::better_enums::_eat_assign<EnumType>)EnumType::expression),
579#define BETTER_ENUMS_EAT_ASSIGN(EnumType, ...) \
581 BETTER_ENUMS_PP_MAP( \
582 BETTER_ENUMS_EAT_ASSIGN_SINGLE, EnumType, __VA_ARGS__))
586#ifdef BETTER_ENUMS_HAVE_CONSTEXPR
590#define BETTER_ENUMS_SELECT_SINGLE_CHARACTER(from, from_length, index) \
591 ::better_enums::_select(from, from_length, index),
593#define BETTER_ENUMS_SELECT_CHARACTERS(from, from_length) \
594 BETTER_ENUMS_ITERATE( \
595 BETTER_ENUMS_SELECT_SINGLE_CHARACTER, from, from_length)
599#define BETTER_ENUMS_TRIM_SINGLE_STRING(ignored, index, expression) \
600constexpr std::size_t _length_ ## index = \
601 ::better_enums::_constant_length(#expression); \
602constexpr const char _trimmed_ ## index [] = \
603 { BETTER_ENUMS_SELECT_CHARACTERS(#expression, _length_ ## index) }; \
604constexpr const char *_final_ ## index = \
605 ::better_enums::_has_initializer(#expression) ? \
606 _trimmed_ ## index : #expression;
608#define BETTER_ENUMS_TRIM_STRINGS(...) \
610 BETTER_ENUMS_PP_MAP( \
611 BETTER_ENUMS_TRIM_SINGLE_STRING, ignored, __VA_ARGS__))
615#define BETTER_ENUMS_REFER_TO_SINGLE_STRING(ignored, index, expression) \
618#define BETTER_ENUMS_REFER_TO_STRINGS(...) \
620 BETTER_ENUMS_PP_MAP( \
621 BETTER_ENUMS_REFER_TO_SINGLE_STRING, ignored, __VA_ARGS__))
629#define BETTER_ENUMS_STRINGIZE_SINGLE(ignored, index, expression) #expression,
631#define BETTER_ENUMS_STRINGIZE(...) \
633 BETTER_ENUMS_PP_MAP( \
634 BETTER_ENUMS_STRINGIZE_SINGLE, ignored, __VA_ARGS__))
636#define BETTER_ENUMS_RESERVE_STORAGE_SINGLE(ignored, index, expression) \
639#define BETTER_ENUMS_RESERVE_STORAGE(...) \
641 BETTER_ENUMS_PP_MAP( \
642 BETTER_ENUMS_RESERVE_STORAGE_SINGLE, ignored, __VA_ARGS__))
648#define BETTER_ENUMS_NS(EnumType) better_enums_data_ ## EnumType
650#ifdef BETTER_ENUMS_VC2008_WORKAROUNDS
652#define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) \
653 BETTER_ENUMS_CONSTEXPR_ Enum(const Enum &other) : \
654 _value(other._value) { }
658#define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum)
662#ifndef BETTER_ENUMS_CLASS_ATTRIBUTE
663# define BETTER_ENUMS_CLASS_ATTRIBUTE
666#define BETTER_ENUMS_TYPE(SetUnderlyingType, SwitchType, GenerateSwitchType, \
667 GenerateStrings, ToStringConstexpr, \
668 DeclareInitialize, DefineInitialize, CallInitialize, \
669 Enum, Underlying, ...) \
671namespace better_enums_data_ ## Enum { \
673BETTER_ENUMS_ID(GenerateSwitchType(Underlying, __VA_ARGS__)) \
677class BETTER_ENUMS_CLASS_ATTRIBUTE Enum { \
679 typedef ::better_enums::optional<Enum> _optional; \
680 typedef ::better_enums::optional<std::size_t> _optional_index; \
683 typedef Underlying _integral; \
685 enum _enumerated SetUnderlyingType(Underlying) { __VA_ARGS__ }; \
687 BETTER_ENUMS_CONSTEXPR_ Enum(_enumerated value) : _value(value) { } \
689 BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) \
691 BETTER_ENUMS_CONSTEXPR_ operator SwitchType(Enum)() const \
693 return SwitchType(Enum)(_value); \
696 BETTER_ENUMS_CONSTEXPR_ _integral _to_integral() const; \
697 BETTER_ENUMS_IF_EXCEPTIONS( \
698 BETTER_ENUMS_CONSTEXPR_ static Enum _from_integral(_integral value); \
700 BETTER_ENUMS_CONSTEXPR_ static Enum \
701 _from_integral_unchecked(_integral value); \
702 BETTER_ENUMS_CONSTEXPR_ static _optional \
703 _from_integral_nothrow(_integral value); \
705 BETTER_ENUMS_CONSTEXPR_ std::size_t _to_index() const; \
706 BETTER_ENUMS_IF_EXCEPTIONS( \
707 BETTER_ENUMS_CONSTEXPR_ static Enum _from_index(std::size_t index); \
709 BETTER_ENUMS_CONSTEXPR_ static Enum \
710 _from_index_unchecked(std::size_t index); \
711 BETTER_ENUMS_CONSTEXPR_ static _optional \
712 _from_index_nothrow(std::size_t index); \
714 ToStringConstexpr const char* _to_string() const; \
715 BETTER_ENUMS_IF_EXCEPTIONS( \
716 BETTER_ENUMS_CONSTEXPR_ static Enum _from_string(const char *name); \
718 BETTER_ENUMS_CONSTEXPR_ static _optional \
719 _from_string_nothrow(const char *name); \
721 BETTER_ENUMS_IF_EXCEPTIONS( \
722 BETTER_ENUMS_CONSTEXPR_ static Enum _from_string_nocase(const char *name); \
724 BETTER_ENUMS_CONSTEXPR_ static _optional \
725 _from_string_nocase_nothrow(const char *name); \
727 BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(_integral value); \
728 BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(const char *name); \
729 BETTER_ENUMS_CONSTEXPR_ static bool _is_valid_nocase(const char *name); \
731 typedef ::better_enums::_iterable<Enum> _value_iterable; \
732 typedef ::better_enums::_iterable<const char*> _name_iterable; \
734 typedef _value_iterable::iterator _value_iterator; \
735 typedef _name_iterable::iterator _name_iterator; \
737 BETTER_ENUMS_CONSTEXPR_ static const std::size_t _size_constant = \
738 BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT(__VA_ARGS__)); \
739 BETTER_ENUMS_CONSTEXPR_ static std::size_t _size() \
740 { return _size_constant; } \
742 BETTER_ENUMS_CONSTEXPR_ static const char* _name(); \
743 BETTER_ENUMS_CONSTEXPR_ static _value_iterable _values(); \
744 ToStringConstexpr static _name_iterable _names(); \
748 BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \
751 explicit BETTER_ENUMS_CONSTEXPR_ Enum(const _integral &value) : \
756 BETTER_ENUMS_CONSTEXPR_ static _optional_index \
757 _from_value_loop(_integral value, std::size_t index = 0); \
758 BETTER_ENUMS_CONSTEXPR_ static _optional_index \
759 _from_string_loop(const char *name, std::size_t index = 0); \
760 BETTER_ENUMS_CONSTEXPR_ static _optional_index \
761 _from_string_nocase_loop(const char *name, std::size_t index = 0); \
763 friend struct ::better_enums::_initialize_at_program_start<Enum>; \
766namespace better_enums_data_ ## Enum { \
768static ::better_enums::_initialize_at_program_start<Enum> \
769 _force_initialization; \
771enum _putNamesInThisScopeAlso { __VA_ARGS__ }; \
773BETTER_ENUMS_IGNORE_OLD_CAST_HEADER \
774BETTER_ENUMS_IGNORE_OLD_CAST_BEGIN \
775BETTER_ENUMS_CONSTEXPR_ const Enum _value_array[] = \
776 { BETTER_ENUMS_ID(BETTER_ENUMS_EAT_ASSIGN(Enum, __VA_ARGS__)) }; \
777BETTER_ENUMS_IGNORE_OLD_CAST_END \
779BETTER_ENUMS_ID(GenerateStrings(Enum, __VA_ARGS__)) \
783BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER \
784BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN \
785BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
787operator +(Enum::_enumerated enumerated) \
789 return static_cast<Enum>(enumerated); \
791BETTER_ENUMS_IGNORE_ATTRIBUTES_END \
793BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \
794Enum::_from_value_loop(Enum::_integral value, std::size_t index) \
798 _optional_index() : \
799 BETTER_ENUMS_NS(Enum)::_value_array[index]._value == value ? \
800 _optional_index(index) : \
801 _from_value_loop(value, index + 1); \
804BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \
805Enum::_from_string_loop(const char *name, std::size_t index) \
808 index == _size() ? _optional_index() : \
809 ::better_enums::_names_match( \
810 BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ? \
811 _optional_index(index) : \
812 _from_string_loop(name, index + 1); \
815BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \
816Enum::_from_string_nocase_loop(const char *name, std::size_t index) \
819 index == _size() ? _optional_index() : \
820 ::better_enums::_names_match_nocase( \
821 BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ? \
822 _optional_index(index) : \
823 _from_string_nocase_loop(name, index + 1); \
826BETTER_ENUMS_CONSTEXPR_ inline Enum::_integral Enum::_to_integral() const \
828 return _integral(_value); \
831BETTER_ENUMS_CONSTEXPR_ inline std::size_t Enum::_to_index() const \
833 return *_from_value_loop(_value); \
836BETTER_ENUMS_CONSTEXPR_ inline Enum \
837Enum::_from_index_unchecked(std::size_t index) \
840 ::better_enums::_or_zero(_from_index_nothrow(index)); \
843BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
844Enum::_from_index_nothrow(std::size_t index) \
849 _optional(BETTER_ENUMS_NS(Enum)::_value_array[index]); \
852BETTER_ENUMS_IF_EXCEPTIONS( \
853BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_index(std::size_t index) \
856 ::better_enums::_or_throw(_from_index_nothrow(index), \
857 #Enum "::_from_index: invalid argument"); \
861BETTER_ENUMS_CONSTEXPR_ inline Enum \
862Enum::_from_integral_unchecked(_integral value) \
864 return static_cast<_enumerated>(value); \
867BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
868Enum::_from_integral_nothrow(_integral value) \
871 ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array, \
872 _from_value_loop(value)); \
875BETTER_ENUMS_IF_EXCEPTIONS( \
876BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_integral(_integral value) \
879 ::better_enums::_or_throw(_from_integral_nothrow(value), \
880 #Enum "::_from_integral: invalid argument"); \
884ToStringConstexpr inline const char* Enum::_to_string() const \
887 ::better_enums::_or_null( \
888 ::better_enums::_map_index<const char*>( \
889 BETTER_ENUMS_NS(Enum)::_name_array(), \
890 _from_value_loop(CallInitialize(_value)))); \
893BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
894Enum::_from_string_nothrow(const char *name) \
897 ::better_enums::_map_index<Enum>( \
898 BETTER_ENUMS_NS(Enum)::_value_array, _from_string_loop(name)); \
901BETTER_ENUMS_IF_EXCEPTIONS( \
902BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string(const char *name) \
905 ::better_enums::_or_throw(_from_string_nothrow(name), \
906 #Enum "::_from_string: invalid argument"); \
910BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \
911Enum::_from_string_nocase_nothrow(const char *name) \
914 ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array, \
915 _from_string_nocase_loop(name)); \
918BETTER_ENUMS_IF_EXCEPTIONS( \
919BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string_nocase(const char *name)\
922 ::better_enums::_or_throw( \
923 _from_string_nocase_nothrow(name), \
924 #Enum "::_from_string_nocase: invalid argument"); \
928BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(_integral value) \
930 return _from_value_loop(value); \
933BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(const char *name) \
935 return _from_string_loop(name); \
938BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid_nocase(const char *name) \
940 return _from_string_nocase_loop(name); \
943BETTER_ENUMS_CONSTEXPR_ inline const char* Enum::_name() \
948BETTER_ENUMS_CONSTEXPR_ inline Enum::_value_iterable Enum::_values() \
950 return _value_iterable(BETTER_ENUMS_NS(Enum)::_value_array, _size()); \
953ToStringConstexpr inline Enum::_name_iterable Enum::_names() \
956 _name_iterable(BETTER_ENUMS_NS(Enum)::_name_array(), \
957 CallInitialize(_size())); \
960DefineInitialize(Enum) \
962BETTER_ENUMS_IGNORE_ATTRIBUTES_HEADER \
963BETTER_ENUMS_IGNORE_ATTRIBUTES_BEGIN \
964BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
965inline bool operator ==(const Enum &a, const Enum &b) \
966 { return a._to_integral() == b._to_integral(); } \
968BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
969inline bool operator !=(const Enum &a, const Enum &b) \
970 { return a._to_integral() != b._to_integral(); } \
972BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
973inline bool operator <(const Enum &a, const Enum &b) \
974 { return a._to_integral() < b._to_integral(); } \
976BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
977inline bool operator <=(const Enum &a, const Enum &b) \
978 { return a._to_integral() <= b._to_integral(); } \
980BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
981inline bool operator >(const Enum &a, const Enum &b) \
982 { return a._to_integral() > b._to_integral(); } \
984BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \
985inline bool operator >=(const Enum &a, const Enum &b) \
986 { return a._to_integral() >= b._to_integral(); } \
987BETTER_ENUMS_IGNORE_ATTRIBUTES_END \
990template <typename Char, typename Traits> \
991std::basic_ostream<Char, Traits>& \
992operator <<(std::basic_ostream<Char, Traits>& stream, const Enum &value) \
994 return stream << value._to_string(); \
997template <typename Char, typename Traits> \
998std::basic_istream<Char, Traits>& \
999operator >>(std::basic_istream<Char, Traits>& stream, Enum &value) \
1001 std::basic_string<Char, Traits> buffer; \
1004 ::better_enums::optional<Enum> converted = \
1005 Enum::_from_string_nothrow(buffer.c_str()); \
1008 value = *converted; \
1010 stream.setstate(std::basic_istream<Char, Traits>::failbit); \
1020#define BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying)
1023#define BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying) \
1026#if defined(_MSC_VER) && _MSC_VER >= 1700
1029# define BETTER_ENUMS_LEGACY_UNDERLYING_TYPE(Underlying) \
1030 BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying)
1032# define BETTER_ENUMS_LEGACY_UNDERLYING_TYPE(Underlying) \
1033 BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying)
1037#define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE(Type) \
1041#define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE(Type) \
1042 BETTER_ENUMS_NS(Type)::_enumClassForSwitchStatements
1045#define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE(Underlying, ...)
1048#define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE(Underlying, ...) \
1049 enum class _enumClassForSwitchStatements : Underlying { __VA_ARGS__ };
1052#define BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS(Enum, ...) \
1053 inline const char** _raw_names() \
1055 static const char *value[] = \
1056 { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) }; \
1060 inline char* _name_storage() \
1062 static char storage[] = \
1063 BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__)); \
1067 inline const char** _name_array() \
1069 static const char *value[Enum::_size_constant]; \
1073 inline bool& _initialized() \
1075 static bool value = false; \
1080#define BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...) \
1081 constexpr const char *_the_raw_names[] = \
1082 { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) }; \
1084 constexpr const char * const * _raw_names() \
1086 return _the_raw_names; \
1089 inline char* _name_storage() \
1091 static char storage[] = \
1092 BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__)); \
1096 inline const char** _name_array() \
1098 static const char *value[Enum::_size_constant]; \
1102 inline bool& _initialized() \
1104 static bool value = false; \
1109#define BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...) \
1110 BETTER_ENUMS_ID(BETTER_ENUMS_TRIM_STRINGS(__VA_ARGS__)) \
1112 constexpr const char * const _the_name_array[] = \
1113 { BETTER_ENUMS_ID(BETTER_ENUMS_REFER_TO_STRINGS(__VA_ARGS__)) }; \
1115 constexpr const char * const * _name_array() \
1117 return _the_name_array; \
1120 constexpr const char * const * _raw_names() \
1122 return _the_name_array; \
1126#define BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD
1129#define BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD \
1133#define BETTER_ENUMS_DO_DECLARE_INITIALIZE \
1134 static int initialize();
1137#define BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE \
1138 static int initialize() { return 0; }
1141#define BETTER_ENUMS_DO_DEFINE_INITIALIZE(Enum) \
1142 inline int Enum::initialize() \
1144 if (BETTER_ENUMS_NS(Enum)::_initialized()) \
1147 ::better_enums::_trim_names(BETTER_ENUMS_NS(Enum)::_raw_names(), \
1148 BETTER_ENUMS_NS(Enum)::_name_array(), \
1149 BETTER_ENUMS_NS(Enum)::_name_storage(), \
1152 BETTER_ENUMS_NS(Enum)::_initialized() = true; \
1158#define BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE(Enum)
1161#define BETTER_ENUMS_DO_CALL_INITIALIZE(value) \
1162 ::better_enums::continue_with(initialize(), value)
1165#define BETTER_ENUMS_DO_NOT_CALL_INITIALIZE(value) \
1172#ifdef BETTER_ENUMS_STRICT_CONVERSION
1173# define BETTER_ENUMS_DEFAULT_SWITCH_TYPE \
1174 BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE
1175# define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE \
1176 BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE
1178# define BETTER_ENUMS_DEFAULT_SWITCH_TYPE \
1179 BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE
1180# define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE \
1181 BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE
1186#ifndef BETTER_ENUMS_DEFAULT_CONSTRUCTOR
1187# define BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \
1189 Enum() : _value(0) { }
1194#ifdef BETTER_ENUMS_HAVE_CONSTEXPR
1196#ifdef BETTER_ENUMS_CONSTEXPR_TO_STRING
1197# define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS \
1198 BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS
1199# define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD \
1200 BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD
1201# define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE \
1202 BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE
1203# define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE \
1204 BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE
1205# define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE \
1206 BETTER_ENUMS_DO_NOT_CALL_INITIALIZE
1208# define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS \
1209 BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS
1210# define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD \
1211 BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD
1212# define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE \
1213 BETTER_ENUMS_DO_DECLARE_INITIALIZE
1214# define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE \
1215 BETTER_ENUMS_DO_DEFINE_INITIALIZE
1216# define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE \
1217 BETTER_ENUMS_DO_CALL_INITIALIZE
1224#define BETTER_ENUM(Enum, Underlying, ...) \
1225 BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \
1226 BETTER_ENUMS_CXX11_UNDERLYING_TYPE, \
1227 BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \
1228 BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \
1229 BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS, \
1230 BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD, \
1231 BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE, \
1232 BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE, \
1233 BETTER_ENUMS_DEFAULT_CALL_INITIALIZE, \
1234 Enum, Underlying, __VA_ARGS__))
1236#define SLOW_ENUM(Enum, Underlying, ...) \
1237 BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \
1238 BETTER_ENUMS_CXX11_UNDERLYING_TYPE, \
1239 BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \
1240 BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \
1241 BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS, \
1242 BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD, \
1243 BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE, \
1244 BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE, \
1245 BETTER_ENUMS_DO_NOT_CALL_INITIALIZE, \
1246 Enum, Underlying, __VA_ARGS__))
1250#define BETTER_ENUM(Enum, Underlying, ...) \
1251 BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \
1252 BETTER_ENUMS_LEGACY_UNDERLYING_TYPE, \
1253 BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \
1254 BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \
1255 BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS, \
1256 BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD, \
1257 BETTER_ENUMS_DO_DECLARE_INITIALIZE, \
1258 BETTER_ENUMS_DO_DEFINE_INITIALIZE, \
1259 BETTER_ENUMS_DO_CALL_INITIALIZE, \
1260 Enum, Underlying, __VA_ARGS__))
1266namespace better_enums {
1270template <
typename T>
1272 BETTER_ENUMS_CONSTEXPR_
static bool less(
const T& a,
const T& b )
1279struct map_compare<const char*> {
1280 BETTER_ENUMS_CONSTEXPR_
static bool less(
const char *a,
const char *b )
1282 return less_loop( a, b );
1286 BETTER_ENUMS_CONSTEXPR_
static bool
1287 less_loop(
const char *a,
const char *b,
size_t index = 0 )
1290 a[index] != b[index] ? a[index] < b[index] :
1291 a[index] ==
'\0' ? false :
1292 less_loop( a, b, index + 1 );
1297struct map_compare<const wchar_t*> {
1298 BETTER_ENUMS_CONSTEXPR_
static bool less(
const wchar_t *a,
const wchar_t *b )
1300 return less_loop( a, b );
1304 BETTER_ENUMS_CONSTEXPR_
static bool
1305 less_loop(
const wchar_t *a,
const wchar_t *b,
size_t index = 0 )
1308 a[index] != b[index] ? a[index] < b[index] :
1309 a[index] == L
'\0' ? false :
1310 less_loop( a, b, index + 1 );
1314template <
typename Enum,
typename T,
typename Compare = map_compare<T> >
1316 typedef T( *function )(Enum);
1318 BETTER_ENUMS_CONSTEXPR_
explicit map( function f ) : _f( f ) { }
1320 BETTER_ENUMS_CONSTEXPR_ T from_enum( Enum value )
const {
return _f( value ); }
1321 BETTER_ENUMS_CONSTEXPR_ T operator []( Enum value )
const
1326 BETTER_ENUMS_CONSTEXPR_ Enum to_enum( T value )
const
1329 _or_throw( to_enum_nothrow( value ),
"map::to_enum: invalid argument" );
1332 BETTER_ENUMS_CONSTEXPR_ optional<Enum>
1333 to_enum_nothrow( T value,
size_t index = 0 )
const
1336 index >= Enum::_size() ? optional<Enum>() :
1337 Compare::less( _f( Enum::_values()[index] ), value ) ||
1338 Compare::less( value, _f( Enum::_values()[index] ) ) ?
1339 to_enum_nothrow( value, index + 1 ) :
1340 Enum::_values()[index];
1347template <
typename Enum,
typename T>
1348BETTER_ENUMS_CONSTEXPR_ map<Enum, T> make_map( T( *f )(Enum) )
1350 return map<Enum, T>( f );
1355#define BETTER_ENUMS_DECLARE_STD_HASH(type) \
1357 template <> struct hash<type> \
1359 size_t operator()(const type &x) const \
1361 return std::hash<size_t>()(x._to_integral()); \