6 #ifndef BETTER_ENUMS_ENUM_H 7 #define BETTER_ENUMS_ENUM_H 22 # if __has_feature(cxx_constexpr) 23 # define BETTER_ENUMS_HAVE_CONSTEXPR 25 # if !defined(__EXCEPTIONS) || !__has_feature(cxx_exceptions) 26 # define BETTER_ENUMS_NO_EXCEPTIONS 29 # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L 30 # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) 31 # define BETTER_ENUMS_HAVE_CONSTEXPR 35 # define BETTER_ENUMS_NO_EXCEPTIONS 42 # define BETTER_ENUMS_HAVE_CONSTEXPR 45 # if __has_feature(cxx_constexpr) 46 # define BETTER_ENUMS_HAVE_CONSTEXPR 50 # define BETTER_ENUMS_NO_EXCEPTIONS 53 # define BETTER_ENUMS_VC2008_WORKAROUNDS 57 #ifdef BETTER_ENUMS_CONSTEXPR 58 # define BETTER_ENUMS_HAVE_CONSTEXPR 61 #ifdef BETTER_ENUMS_NO_CONSTEXPR 62 # ifdef BETTER_ENUMS_HAVE_CONSTEXPR 63 # undef BETTER_ENUMS_HAVE_CONSTEXPR 75 #ifdef BETTER_ENUMS_HAVE_CONSTEXPR 76 # define BETTER_ENUMS_CONSTEXPR_ constexpr 77 # define BETTER_ENUMS_NULLPTR nullptr 79 # define BETTER_ENUMS_CONSTEXPR_ 80 # define BETTER_ENUMS_NULLPTR NULL 83 #ifndef BETTER_ENUMS_NO_EXCEPTIONS 84 # define BETTER_ENUMS_IF_EXCEPTIONS(x) x 86 # define BETTER_ENUMS_IF_EXCEPTIONS(x) 90 # define BETTER_ENUMS_UNUSED __attribute__((__unused__)) 92 # define BETTER_ENUMS_UNUSED 99 #ifdef BETTER_ENUMS_MACRO_FILE 100 # include BETTER_ENUMS_MACRO_FILE 103 #define BETTER_ENUMS_PP_MAP(macro, data, ...) \ 105 BETTER_ENUMS_APPLY( \ 106 BETTER_ENUMS_PP_MAP_VAR_COUNT, \ 107 BETTER_ENUMS_PP_COUNT(__VA_ARGS__)) \ 108 (macro, data, __VA_ARGS__)) 110 #define BETTER_ENUMS_PP_MAP_VAR_COUNT(count) BETTER_ENUMS_M ## count 112 #define BETTER_ENUMS_APPLY(macro, ...) BETTER_ENUMS_ID(macro(__VA_ARGS__)) 114 #define BETTER_ENUMS_ID(x) x 116 #define BETTER_ENUMS_M1(m, d, x) m(d,0,x) 117 #define BETTER_ENUMS_M2(m,d,x,...) m(d,1,x) \ 118 BETTER_ENUMS_ID(BETTER_ENUMS_M1(m,d,__VA_ARGS__)) 119 #define BETTER_ENUMS_M3(m,d,x,...) m(d,2,x) \ 120 BETTER_ENUMS_ID(BETTER_ENUMS_M2(m,d,__VA_ARGS__)) 121 #define BETTER_ENUMS_M4(m,d,x,...) m(d,3,x) \ 122 BETTER_ENUMS_ID(BETTER_ENUMS_M3(m,d,__VA_ARGS__)) 123 #define BETTER_ENUMS_M5(m,d,x,...) m(d,4,x) \ 124 BETTER_ENUMS_ID(BETTER_ENUMS_M4(m,d,__VA_ARGS__)) 125 #define BETTER_ENUMS_M6(m,d,x,...) m(d,5,x) \ 126 BETTER_ENUMS_ID(BETTER_ENUMS_M5(m,d,__VA_ARGS__)) 127 #define BETTER_ENUMS_M7(m,d,x,...) m(d,6,x) \ 128 BETTER_ENUMS_ID(BETTER_ENUMS_M6(m,d,__VA_ARGS__)) 129 #define BETTER_ENUMS_M8(m,d,x,...) m(d,7,x) \ 130 BETTER_ENUMS_ID(BETTER_ENUMS_M7(m,d,__VA_ARGS__)) 131 #define BETTER_ENUMS_M9(m,d,x,...) m(d,8,x) \ 132 BETTER_ENUMS_ID(BETTER_ENUMS_M8(m,d,__VA_ARGS__)) 133 #define BETTER_ENUMS_M10(m,d,x,...) m(d,9,x) \ 134 BETTER_ENUMS_ID(BETTER_ENUMS_M9(m,d,__VA_ARGS__)) 135 #define BETTER_ENUMS_M11(m,d,x,...) m(d,10,x) \ 136 BETTER_ENUMS_ID(BETTER_ENUMS_M10(m,d,__VA_ARGS__)) 137 #define BETTER_ENUMS_M12(m,d,x,...) m(d,11,x) \ 138 BETTER_ENUMS_ID(BETTER_ENUMS_M11(m,d,__VA_ARGS__)) 139 #define BETTER_ENUMS_M13(m,d,x,...) m(d,12,x) \ 140 BETTER_ENUMS_ID(BETTER_ENUMS_M12(m,d,__VA_ARGS__)) 141 #define BETTER_ENUMS_M14(m,d,x,...) m(d,13,x) \ 142 BETTER_ENUMS_ID(BETTER_ENUMS_M13(m,d,__VA_ARGS__)) 143 #define BETTER_ENUMS_M15(m,d,x,...) m(d,14,x) \ 144 BETTER_ENUMS_ID(BETTER_ENUMS_M14(m,d,__VA_ARGS__)) 145 #define BETTER_ENUMS_M16(m,d,x,...) m(d,15,x) \ 146 BETTER_ENUMS_ID(BETTER_ENUMS_M15(m,d,__VA_ARGS__)) 147 #define BETTER_ENUMS_M17(m,d,x,...) m(d,16,x) \ 148 BETTER_ENUMS_ID(BETTER_ENUMS_M16(m,d,__VA_ARGS__)) 149 #define BETTER_ENUMS_M18(m,d,x,...) m(d,17,x) \ 150 BETTER_ENUMS_ID(BETTER_ENUMS_M17(m,d,__VA_ARGS__)) 151 #define BETTER_ENUMS_M19(m,d,x,...) m(d,18,x) \ 152 BETTER_ENUMS_ID(BETTER_ENUMS_M18(m,d,__VA_ARGS__)) 153 #define BETTER_ENUMS_M20(m,d,x,...) m(d,19,x) \ 154 BETTER_ENUMS_ID(BETTER_ENUMS_M19(m,d,__VA_ARGS__)) 155 #define BETTER_ENUMS_M21(m,d,x,...) m(d,20,x) \ 156 BETTER_ENUMS_ID(BETTER_ENUMS_M20(m,d,__VA_ARGS__)) 157 #define BETTER_ENUMS_M22(m,d,x,...) m(d,21,x) \ 158 BETTER_ENUMS_ID(BETTER_ENUMS_M21(m,d,__VA_ARGS__)) 159 #define BETTER_ENUMS_M23(m,d,x,...) m(d,22,x) \ 160 BETTER_ENUMS_ID(BETTER_ENUMS_M22(m,d,__VA_ARGS__)) 161 #define BETTER_ENUMS_M24(m,d,x,...) m(d,23,x) \ 162 BETTER_ENUMS_ID(BETTER_ENUMS_M23(m,d,__VA_ARGS__)) 163 #define BETTER_ENUMS_M25(m,d,x,...) m(d,24,x) \ 164 BETTER_ENUMS_ID(BETTER_ENUMS_M24(m,d,__VA_ARGS__)) 165 #define BETTER_ENUMS_M26(m,d,x,...) m(d,25,x) \ 166 BETTER_ENUMS_ID(BETTER_ENUMS_M25(m,d,__VA_ARGS__)) 167 #define BETTER_ENUMS_M27(m,d,x,...) m(d,26,x) \ 168 BETTER_ENUMS_ID(BETTER_ENUMS_M26(m,d,__VA_ARGS__)) 169 #define BETTER_ENUMS_M28(m,d,x,...) m(d,27,x) \ 170 BETTER_ENUMS_ID(BETTER_ENUMS_M27(m,d,__VA_ARGS__)) 171 #define BETTER_ENUMS_M29(m,d,x,...) m(d,28,x) \ 172 BETTER_ENUMS_ID(BETTER_ENUMS_M28(m,d,__VA_ARGS__)) 173 #define BETTER_ENUMS_M30(m,d,x,...) m(d,29,x) \ 174 BETTER_ENUMS_ID(BETTER_ENUMS_M29(m,d,__VA_ARGS__)) 175 #define BETTER_ENUMS_M31(m,d,x,...) m(d,30,x) \ 176 BETTER_ENUMS_ID(BETTER_ENUMS_M30(m,d,__VA_ARGS__)) 177 #define BETTER_ENUMS_M32(m,d,x,...) m(d,31,x) \ 178 BETTER_ENUMS_ID(BETTER_ENUMS_M31(m,d,__VA_ARGS__)) 179 #define BETTER_ENUMS_M33(m,d,x,...) m(d,32,x) \ 180 BETTER_ENUMS_ID(BETTER_ENUMS_M32(m,d,__VA_ARGS__)) 181 #define BETTER_ENUMS_M34(m,d,x,...) m(d,33,x) \ 182 BETTER_ENUMS_ID(BETTER_ENUMS_M33(m,d,__VA_ARGS__)) 183 #define BETTER_ENUMS_M35(m,d,x,...) m(d,34,x) \ 184 BETTER_ENUMS_ID(BETTER_ENUMS_M34(m,d,__VA_ARGS__)) 185 #define BETTER_ENUMS_M36(m,d,x,...) m(d,35,x) \ 186 BETTER_ENUMS_ID(BETTER_ENUMS_M35(m,d,__VA_ARGS__)) 187 #define BETTER_ENUMS_M37(m,d,x,...) m(d,36,x) \ 188 BETTER_ENUMS_ID(BETTER_ENUMS_M36(m,d,__VA_ARGS__)) 189 #define BETTER_ENUMS_M38(m,d,x,...) m(d,37,x) \ 190 BETTER_ENUMS_ID(BETTER_ENUMS_M37(m,d,__VA_ARGS__)) 191 #define BETTER_ENUMS_M39(m,d,x,...) m(d,38,x) \ 192 BETTER_ENUMS_ID(BETTER_ENUMS_M38(m,d,__VA_ARGS__)) 193 #define BETTER_ENUMS_M40(m,d,x,...) m(d,39,x) \ 194 BETTER_ENUMS_ID(BETTER_ENUMS_M39(m,d,__VA_ARGS__)) 195 #define BETTER_ENUMS_M41(m,d,x,...) m(d,40,x) \ 196 BETTER_ENUMS_ID(BETTER_ENUMS_M40(m,d,__VA_ARGS__)) 197 #define BETTER_ENUMS_M42(m,d,x,...) m(d,41,x) \ 198 BETTER_ENUMS_ID(BETTER_ENUMS_M41(m,d,__VA_ARGS__)) 199 #define BETTER_ENUMS_M43(m,d,x,...) m(d,42,x) \ 200 BETTER_ENUMS_ID(BETTER_ENUMS_M42(m,d,__VA_ARGS__)) 201 #define BETTER_ENUMS_M44(m,d,x,...) m(d,43,x) \ 202 BETTER_ENUMS_ID(BETTER_ENUMS_M43(m,d,__VA_ARGS__)) 203 #define BETTER_ENUMS_M45(m,d,x,...) m(d,44,x) \ 204 BETTER_ENUMS_ID(BETTER_ENUMS_M44(m,d,__VA_ARGS__)) 205 #define BETTER_ENUMS_M46(m,d,x,...) m(d,45,x) \ 206 BETTER_ENUMS_ID(BETTER_ENUMS_M45(m,d,__VA_ARGS__)) 207 #define BETTER_ENUMS_M47(m,d,x,...) m(d,46,x) \ 208 BETTER_ENUMS_ID(BETTER_ENUMS_M46(m,d,__VA_ARGS__)) 209 #define BETTER_ENUMS_M48(m,d,x,...) m(d,47,x) \ 210 BETTER_ENUMS_ID(BETTER_ENUMS_M47(m,d,__VA_ARGS__)) 211 #define BETTER_ENUMS_M49(m,d,x,...) m(d,48,x) \ 212 BETTER_ENUMS_ID(BETTER_ENUMS_M48(m,d,__VA_ARGS__)) 213 #define BETTER_ENUMS_M50(m,d,x,...) m(d,49,x) \ 214 BETTER_ENUMS_ID(BETTER_ENUMS_M49(m,d,__VA_ARGS__)) 215 #define BETTER_ENUMS_M51(m,d,x,...) m(d,50,x) \ 216 BETTER_ENUMS_ID(BETTER_ENUMS_M50(m,d,__VA_ARGS__)) 217 #define BETTER_ENUMS_M52(m,d,x,...) m(d,51,x) \ 218 BETTER_ENUMS_ID(BETTER_ENUMS_M51(m,d,__VA_ARGS__)) 219 #define BETTER_ENUMS_M53(m,d,x,...) m(d,52,x) \ 220 BETTER_ENUMS_ID(BETTER_ENUMS_M52(m,d,__VA_ARGS__)) 221 #define BETTER_ENUMS_M54(m,d,x,...) m(d,53,x) \ 222 BETTER_ENUMS_ID(BETTER_ENUMS_M53(m,d,__VA_ARGS__)) 223 #define BETTER_ENUMS_M55(m,d,x,...) m(d,54,x) \ 224 BETTER_ENUMS_ID(BETTER_ENUMS_M54(m,d,__VA_ARGS__)) 225 #define BETTER_ENUMS_M56(m,d,x,...) m(d,55,x) \ 226 BETTER_ENUMS_ID(BETTER_ENUMS_M55(m,d,__VA_ARGS__)) 227 #define BETTER_ENUMS_M57(m,d,x,...) m(d,56,x) \ 228 BETTER_ENUMS_ID(BETTER_ENUMS_M56(m,d,__VA_ARGS__)) 229 #define BETTER_ENUMS_M58(m,d,x,...) m(d,57,x) \ 230 BETTER_ENUMS_ID(BETTER_ENUMS_M57(m,d,__VA_ARGS__)) 231 #define BETTER_ENUMS_M59(m,d,x,...) m(d,58,x) \ 232 BETTER_ENUMS_ID(BETTER_ENUMS_M58(m,d,__VA_ARGS__)) 233 #define BETTER_ENUMS_M60(m,d,x,...) m(d,59,x) \ 234 BETTER_ENUMS_ID(BETTER_ENUMS_M59(m,d,__VA_ARGS__)) 235 #define BETTER_ENUMS_M61(m,d,x,...) m(d,60,x) \ 236 BETTER_ENUMS_ID(BETTER_ENUMS_M60(m,d,__VA_ARGS__)) 237 #define BETTER_ENUMS_M62(m,d,x,...) m(d,61,x) \ 238 BETTER_ENUMS_ID(BETTER_ENUMS_M61(m,d,__VA_ARGS__)) 239 #define BETTER_ENUMS_M63(m,d,x,...) m(d,62,x) \ 240 BETTER_ENUMS_ID(BETTER_ENUMS_M62(m,d,__VA_ARGS__)) 241 #define BETTER_ENUMS_M64(m,d,x,...) m(d,63,x) \ 242 BETTER_ENUMS_ID(BETTER_ENUMS_M63(m,d,__VA_ARGS__)) 244 #define BETTER_ENUMS_PP_COUNT_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ 245 _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \ 246 _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ 247 _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, \ 248 _56, _57, _58, _59, _60, _61, _62, _63, _64, count, ...) count 250 #define BETTER_ENUMS_PP_COUNT(...) \ 251 BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60,\ 252 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42,\ 253 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24,\ 254 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, \ 257 #define BETTER_ENUMS_ITERATE(X, f, l) X(f, l, 0) X(f, l, 1) X(f, l, 2) \ 258 X(f, l, 3) X(f, l, 4) X(f, l, 5) X(f, l, 6) X(f, l, 7) X(f, l, 8) \ 259 X(f, l, 9) X(f, l, 10) X(f, l, 11) X(f, l, 12) X(f, l, 13) X(f, l, 14) \ 260 X(f, l, 15) X(f, l, 16) X(f, l, 17) X(f, l, 18) X(f, l, 19) X(f, l, 20) \ 261 X(f, l, 21) X(f, l, 22) X(f, l, 23) 263 #endif // #ifdef BETTER_ENUMS_MACRO_FILE else case 272 template <
typename T>
273 BETTER_ENUMS_CONSTEXPR_
inline T _default()
275 return static_cast<typename T::_enumerated
>(0);
279 BETTER_ENUMS_CONSTEXPR_
inline const char* _default<const char*>()
281 return BETTER_ENUMS_NULLPTR;
285 BETTER_ENUMS_CONSTEXPR_
inline std::size_t _default<std::size_t>()
290 template <
typename T>
292 BETTER_ENUMS_CONSTEXPR_
optional() :
293 _valid(
false), _value(_default<T>()) { }
295 BETTER_ENUMS_CONSTEXPR_
optional(T v) : _valid(
true), _value(v) { }
297 BETTER_ENUMS_CONSTEXPR_
const T& operator *()
const {
return _value; }
298 BETTER_ENUMS_CONSTEXPR_
const T* operator ->()
const {
return &_value; }
300 BETTER_ENUMS_CONSTEXPR_
operator bool()
const {
return _valid; }
302 BETTER_ENUMS_CONSTEXPR_
const T& value()
const {
return _value; }
309 template <
typename CastTo,
typename Element>
316 #ifdef BETTER_ENUMS_VC2008_WORKAROUNDS 318 #define BETTER_ENUMS_OR_THROW \ 320 throw std::runtime_error(message); \ 326 #define BETTER_ENUMS_OR_THROW \ 327 return maybe ? *maybe : throw std::runtime_error(message); 331 BETTER_ENUMS_IF_EXCEPTIONS(
332 template <typename T>
333 BETTER_ENUMS_CONSTEXPR_
static T _or_throw(optional<T> maybe,
336 BETTER_ENUMS_OR_THROW
340 template <typename T>
341 BETTER_ENUMS_CONSTEXPR_
static T* _or_null(optional<T*> maybe)
343 return maybe ? *maybe : BETTER_ENUMS_NULLPTR;
346 template <
typename T>
347 BETTER_ENUMS_CONSTEXPR_
static T _or_zero(optional<T> maybe)
349 return maybe ? *maybe : T::_from_integral_unchecked(0);
359 template <
typename T,
typename U>
360 BETTER_ENUMS_CONSTEXPR_ U
361 continue_with(T, U value) {
return value; }
367 template <
typename EnumType>
369 explicit BETTER_ENUMS_CONSTEXPR_
_eat_assign(EnumType value) : _value(value)
372 template <
typename Any>
374 operator =(Any)
const {
return *
this; }
376 BETTER_ENUMS_CONSTEXPR_
operator EnumType ()
const {
return _value; }
386 template <
typename Element>
388 typedef const Element* iterator;
390 BETTER_ENUMS_CONSTEXPR_ iterator begin()
const {
return iterator(_array); }
391 BETTER_ENUMS_CONSTEXPR_ iterator end()
const 392 {
return iterator(_array + _size); }
393 BETTER_ENUMS_CONSTEXPR_ std::size_t size()
const {
return _size; }
394 BETTER_ENUMS_CONSTEXPR_
const Element& operator [](std::size_t index)
const 395 {
return _array[index]; }
397 BETTER_ENUMS_CONSTEXPR_
_iterable(
const Element *array, std::size_t s) :
398 _array(array), _size(s) { }
401 const Element *
const _array;
402 const std::size_t _size;
409 BETTER_ENUMS_CONSTEXPR_
static const char *_name_enders =
"= \t\n";
411 BETTER_ENUMS_CONSTEXPR_
inline bool _ends_name(
char c, std::size_t index = 0)
414 c == _name_enders[index] ? true :
415 _name_enders[index] ==
'\0' ? false :
416 _ends_name(c, index + 1);
419 BETTER_ENUMS_CONSTEXPR_
inline bool _has_initializer(
const char *s,
420 std::size_t index = 0)
423 s[index] ==
'\0' ? false :
424 s[index] ==
'=' ? true :
425 _has_initializer(s, index + 1);
428 BETTER_ENUMS_CONSTEXPR_
inline std::size_t
429 _constant_length(
const char *s, std::size_t index = 0)
431 return _ends_name(s[index]) ? index : _constant_length(s, index + 1);
434 BETTER_ENUMS_CONSTEXPR_
inline char 435 _select(
const char *from, std::size_t from_length, std::size_t index)
437 return index >= from_length ?
'\0' : from[index];
440 BETTER_ENUMS_CONSTEXPR_
inline char _to_lower_ascii(
char c)
442 return c >= 0x41 && c <= 0x5A ? static_cast<char>(c + 0x20) : c;
445 BETTER_ENUMS_CONSTEXPR_
inline bool _names_match(
const char *stringizedName,
446 const char *referenceName,
447 std::size_t index = 0)
450 _ends_name(stringizedName[index]) ? referenceName[index] ==
'\0' :
451 referenceName[index] ==
'\0' ? false :
452 stringizedName[index] != referenceName[index] ? false :
453 _names_match(stringizedName, referenceName, index + 1);
456 BETTER_ENUMS_CONSTEXPR_
inline bool 457 _names_match_nocase(
const char *stringizedName,
const char *referenceName,
458 std::size_t index = 0)
461 _ends_name(stringizedName[index]) ? referenceName[index] ==
'\0' :
462 referenceName[index] ==
'\0' ? false :
463 _to_lower_ascii(stringizedName[index]) !=
464 _to_lower_ascii(referenceName[index]) ? false :
465 _names_match_nocase(stringizedName, referenceName, index + 1);
468 inline void _trim_names(
const char *
const *raw_names,
469 const char **trimmed_names,
470 char *storage, std::size_t count)
472 std::size_t offset = 0;
474 for (std::size_t index = 0; index < count; ++index) {
475 trimmed_names[index] = storage + offset;
477 std::size_t trimmed_length =
478 std::strcspn(raw_names[index], _name_enders);
479 storage[offset + trimmed_length] =
'\0';
481 std::size_t raw_length = std::strlen(raw_names[index]);
482 offset += raw_length + 1;
489 template <
typename Enum>
500 #define BETTER_ENUMS_EAT_ASSIGN_SINGLE(EnumType, index, expression) \ 501 (EnumType)((::better_enums::_eat_assign<EnumType>)EnumType::expression), 503 #define BETTER_ENUMS_EAT_ASSIGN(EnumType, ...) \ 505 BETTER_ENUMS_PP_MAP( \ 506 BETTER_ENUMS_EAT_ASSIGN_SINGLE, EnumType, __VA_ARGS__)) 510 #ifdef BETTER_ENUMS_HAVE_CONSTEXPR 514 #define BETTER_ENUMS_SELECT_SINGLE_CHARACTER(from, from_length, index) \ 515 ::better_enums::_select(from, from_length, index), 517 #define BETTER_ENUMS_SELECT_CHARACTERS(from, from_length) \ 518 BETTER_ENUMS_ITERATE( \ 519 BETTER_ENUMS_SELECT_SINGLE_CHARACTER, from, from_length) 523 #define BETTER_ENUMS_TRIM_SINGLE_STRING(ignored, index, expression) \ 524 constexpr std::size_t _length_ ## index = \ 525 ::better_enums::_constant_length(#expression); \ 526 constexpr const char _trimmed_ ## index [] = \ 527 { BETTER_ENUMS_SELECT_CHARACTERS(#expression, _length_ ## index) }; \ 528 constexpr const char *_final_ ## index = \ 529 ::better_enums::_has_initializer(#expression) ? \ 530 _trimmed_ ## index : #expression; 532 #define BETTER_ENUMS_TRIM_STRINGS(...) \ 534 BETTER_ENUMS_PP_MAP( \ 535 BETTER_ENUMS_TRIM_SINGLE_STRING, ignored, __VA_ARGS__)) 539 #define BETTER_ENUMS_REFER_TO_SINGLE_STRING(ignored, index, expression) \ 542 #define BETTER_ENUMS_REFER_TO_STRINGS(...) \ 544 BETTER_ENUMS_PP_MAP( \ 545 BETTER_ENUMS_REFER_TO_SINGLE_STRING, ignored, __VA_ARGS__)) 549 #endif // #ifdef BETTER_ENUMS_HAVE_CONSTEXPR 553 #define BETTER_ENUMS_STRINGIZE_SINGLE(ignored, index, expression) #expression, 555 #define BETTER_ENUMS_STRINGIZE(...) \ 557 BETTER_ENUMS_PP_MAP( \ 558 BETTER_ENUMS_STRINGIZE_SINGLE, ignored, __VA_ARGS__)) 560 #define BETTER_ENUMS_RESERVE_STORAGE_SINGLE(ignored, index, expression) \ 563 #define BETTER_ENUMS_RESERVE_STORAGE(...) \ 565 BETTER_ENUMS_PP_MAP( \ 566 BETTER_ENUMS_RESERVE_STORAGE_SINGLE, ignored, __VA_ARGS__)) 572 #define BETTER_ENUMS_NS(EnumType) better_enums_data_ ## EnumType 574 #ifdef BETTER_ENUMS_VC2008_WORKAROUNDS 576 #define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) \ 577 BETTER_ENUMS_CONSTEXPR_ Enum(const Enum &other) : \ 578 _value(other._value) { } 582 #define BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) 586 #define BETTER_ENUMS_TYPE(SetUnderlyingType, SwitchType, GenerateSwitchType, \ 587 GenerateStrings, ToStringConstexpr, \ 588 DeclareInitialize, DefineInitialize, CallInitialize, \ 589 Enum, Underlying, ...) \ 591 namespace better_enums_data_ ## Enum { \ 593 BETTER_ENUMS_ID(GenerateSwitchType(Underlying, __VA_ARGS__)) \ 599 typedef ::better_enums::optional<Enum> _optional; \ 600 typedef ::better_enums::optional<std::size_t> _optional_index; \ 603 typedef Underlying _integral; \ 605 enum _enumerated SetUnderlyingType(Underlying) { __VA_ARGS__ }; \ 607 BETTER_ENUMS_CONSTEXPR_ Enum(_enumerated value) : _value(value) { } \ 609 BETTER_ENUMS_COPY_CONSTRUCTOR(Enum) \ 611 BETTER_ENUMS_CONSTEXPR_ operator SwitchType(Enum)() const \ 613 return SwitchType(Enum)(_value); \ 616 BETTER_ENUMS_CONSTEXPR_ _integral _to_integral() const; \ 617 BETTER_ENUMS_IF_EXCEPTIONS( \ 618 BETTER_ENUMS_CONSTEXPR_ static Enum _from_integral(_integral value); \ 620 BETTER_ENUMS_CONSTEXPR_ static Enum \ 621 _from_integral_unchecked(_integral value); \ 622 BETTER_ENUMS_CONSTEXPR_ static _optional \ 623 _from_integral_nothrow(_integral value); \ 625 BETTER_ENUMS_CONSTEXPR_ std::size_t _to_index() const; \ 626 BETTER_ENUMS_IF_EXCEPTIONS( \ 627 BETTER_ENUMS_CONSTEXPR_ static Enum _from_index(std::size_t value); \ 629 BETTER_ENUMS_CONSTEXPR_ static Enum \ 630 _from_index_unchecked(std::size_t value); \ 631 BETTER_ENUMS_CONSTEXPR_ static _optional \ 632 _from_index_nothrow(std::size_t value); \ 634 ToStringConstexpr const char* _to_string() const; \ 635 BETTER_ENUMS_IF_EXCEPTIONS( \ 636 BETTER_ENUMS_CONSTEXPR_ static Enum _from_string(const char *name); \ 638 BETTER_ENUMS_CONSTEXPR_ static _optional \ 639 _from_string_nothrow(const char *name); \ 641 BETTER_ENUMS_IF_EXCEPTIONS( \ 642 BETTER_ENUMS_CONSTEXPR_ static Enum _from_string_nocase(const char *name); \ 644 BETTER_ENUMS_CONSTEXPR_ static _optional \ 645 _from_string_nocase_nothrow(const char *name); \ 647 BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(_integral value); \ 648 BETTER_ENUMS_CONSTEXPR_ static bool _is_valid(const char *name); \ 649 BETTER_ENUMS_CONSTEXPR_ static bool _is_valid_nocase(const char *name); \ 651 typedef ::better_enums::_iterable<Enum> _value_iterable; \ 652 typedef ::better_enums::_iterable<const char*> _name_iterable; \ 654 typedef _value_iterable::iterator _value_iterator; \ 655 typedef _name_iterable::iterator _name_iterator; \ 657 BETTER_ENUMS_CONSTEXPR_ static const std::size_t _size_constant = \ 658 BETTER_ENUMS_ID(BETTER_ENUMS_PP_COUNT(__VA_ARGS__)); \ 659 BETTER_ENUMS_CONSTEXPR_ static std::size_t _size() \ 660 { return _size_constant; } \ 662 BETTER_ENUMS_CONSTEXPR_ static const char* _name(); \ 663 BETTER_ENUMS_CONSTEXPR_ static _value_iterable _values(); \ 664 ToStringConstexpr static _name_iterable _names(); \ 668 BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \ 671 explicit BETTER_ENUMS_CONSTEXPR_ Enum(const _integral &value) : \ 676 BETTER_ENUMS_CONSTEXPR_ static _optional_index \ 677 _from_value_loop(_integral value, std::size_t index = 0); \ 678 BETTER_ENUMS_CONSTEXPR_ static _optional_index \ 679 _from_string_loop(const char *name, std::size_t index = 0); \ 680 BETTER_ENUMS_CONSTEXPR_ static _optional_index \ 681 _from_string_nocase_loop(const char *name, std::size_t index = 0); \ 683 friend struct ::better_enums::_initialize_at_program_start<Enum>; \ 686 namespace better_enums_data_ ## Enum { \ 688 static ::better_enums::_initialize_at_program_start<Enum> \ 689 _force_initialization; \ 691 enum _putNamesInThisScopeAlso { __VA_ARGS__ }; \ 693 BETTER_ENUMS_CONSTEXPR_ const Enum _value_array[] = \ 694 { BETTER_ENUMS_ID(BETTER_ENUMS_EAT_ASSIGN(Enum, __VA_ARGS__)) }; \ 696 BETTER_ENUMS_ID(GenerateStrings(Enum, __VA_ARGS__)) \ 700 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 702 operator +(Enum::_enumerated enumerated) \ 704 return static_cast<Enum>(enumerated); \ 707 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \ 708 Enum::_from_value_loop(Enum::_integral value, std::size_t index) \ 712 _optional_index() : \ 713 BETTER_ENUMS_NS(Enum)::_value_array[index]._value == value ? \ 714 _optional_index(index) : \ 715 _from_value_loop(value, index + 1); \ 718 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \ 719 Enum::_from_string_loop(const char *name, std::size_t index) \ 722 index == _size() ? _optional_index() : \ 723 ::better_enums::_names_match( \ 724 BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ? \ 725 _optional_index(index) : \ 726 _from_string_loop(name, index + 1); \ 729 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional_index \ 730 Enum::_from_string_nocase_loop(const char *name, std::size_t index) \ 733 index == _size() ? _optional_index() : \ 734 ::better_enums::_names_match_nocase( \ 735 BETTER_ENUMS_NS(Enum)::_raw_names()[index], name) ? \ 736 _optional_index(index) : \ 737 _from_string_nocase_loop(name, index + 1); \ 740 BETTER_ENUMS_CONSTEXPR_ inline Enum::_integral Enum::_to_integral() const \ 742 return _integral(_value); \ 745 BETTER_ENUMS_CONSTEXPR_ inline std::size_t Enum::_to_index() const \ 747 return *_from_value_loop(_value); \ 750 BETTER_ENUMS_CONSTEXPR_ inline Enum \ 751 Enum::_from_index_unchecked(std::size_t index) \ 754 ::better_enums::_or_zero(_from_index_nothrow(index)); \ 757 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \ 758 Enum::_from_index_nothrow(std::size_t index) \ 763 _optional(BETTER_ENUMS_NS(Enum)::_value_array[index]); \ 766 BETTER_ENUMS_IF_EXCEPTIONS( \ 767 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_index(std::size_t index) \ 770 ::better_enums::_or_throw(_from_index_nothrow(index), \ 771 #Enum "::_from_index: invalid argument"); \ 775 BETTER_ENUMS_CONSTEXPR_ inline Enum \ 776 Enum::_from_integral_unchecked(_integral value) \ 778 return static_cast<_enumerated>(value); \ 781 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \ 782 Enum::_from_integral_nothrow(_integral value) \ 785 ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array, \ 786 _from_value_loop(value)); \ 789 BETTER_ENUMS_IF_EXCEPTIONS( \ 790 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_integral(_integral value) \ 793 ::better_enums::_or_throw(_from_integral_nothrow(value), \ 794 #Enum "::_from_integral: invalid argument"); \ 798 ToStringConstexpr inline const char* Enum::_to_string() const \ 801 ::better_enums::_or_null( \ 802 ::better_enums::_map_index<const char*>( \ 803 BETTER_ENUMS_NS(Enum)::_name_array(), \ 804 _from_value_loop(CallInitialize(_value)))); \ 807 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \ 808 Enum::_from_string_nothrow(const char *name) \ 811 ::better_enums::_map_index<Enum>( \ 812 BETTER_ENUMS_NS(Enum)::_value_array, _from_string_loop(name)); \ 815 BETTER_ENUMS_IF_EXCEPTIONS( \ 816 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string(const char *name) \ 819 ::better_enums::_or_throw(_from_string_nothrow(name), \ 820 #Enum "::_from_string: invalid argument"); \ 824 BETTER_ENUMS_CONSTEXPR_ inline Enum::_optional \ 825 Enum::_from_string_nocase_nothrow(const char *name) \ 828 ::better_enums::_map_index<Enum>(BETTER_ENUMS_NS(Enum)::_value_array, \ 829 _from_string_nocase_loop(name)); \ 832 BETTER_ENUMS_IF_EXCEPTIONS( \ 833 BETTER_ENUMS_CONSTEXPR_ inline Enum Enum::_from_string_nocase(const char *name)\ 836 ::better_enums::_or_throw( \ 837 _from_string_nocase_nothrow(name), \ 838 #Enum "::_from_string_nocase: invalid argument"); \ 842 BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(_integral value) \ 844 return _from_value_loop(value); \ 847 BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid(const char *name) \ 849 return _from_string_loop(name); \ 852 BETTER_ENUMS_CONSTEXPR_ inline bool Enum::_is_valid_nocase(const char *name) \ 854 return _from_string_nocase_loop(name); \ 857 BETTER_ENUMS_CONSTEXPR_ inline const char* Enum::_name() \ 862 BETTER_ENUMS_CONSTEXPR_ inline Enum::_value_iterable Enum::_values() \ 864 return _value_iterable(BETTER_ENUMS_NS(Enum)::_value_array, _size()); \ 867 ToStringConstexpr inline Enum::_name_iterable Enum::_names() \ 870 _name_iterable(BETTER_ENUMS_NS(Enum)::_name_array(), \ 871 CallInitialize(_size())); \ 874 DefineInitialize(Enum) \ 876 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 877 inline bool operator ==(const Enum &a, const Enum &b) \ 878 { return a._to_integral() == b._to_integral(); } \ 880 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 881 inline bool operator !=(const Enum &a, const Enum &b) \ 882 { return a._to_integral() != b._to_integral(); } \ 884 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 885 inline bool operator <(const Enum &a, const Enum &b) \ 886 { return a._to_integral() < b._to_integral(); } \ 888 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 889 inline bool operator <=(const Enum &a, const Enum &b) \ 890 { return a._to_integral() <= b._to_integral(); } \ 892 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 893 inline bool operator >(const Enum &a, const Enum &b) \ 894 { return a._to_integral() > b._to_integral(); } \ 896 BETTER_ENUMS_UNUSED BETTER_ENUMS_CONSTEXPR_ \ 897 inline bool operator >=(const Enum &a, const Enum &b) \ 898 { return a._to_integral() >= b._to_integral(); } \ 901 template <typename Char, typename Traits> \ 902 std::basic_ostream<Char, Traits>& \ 903 operator <<(std::basic_ostream<Char, Traits>& stream, const Enum &value) \ 905 return stream << value._to_string(); \ 908 template <typename Char, typename Traits> \ 909 std::basic_istream<Char, Traits>& \ 910 operator >>(std::basic_istream<Char, Traits>& stream, Enum &value) \ 912 std::basic_string<Char, Traits> buffer; \ 915 ::better_enums::optional<Enum> converted = \ 916 Enum::_from_string_nothrow(buffer.c_str()); \ 919 value = *converted; \ 921 stream.setstate(std::basic_istream<Char, Traits>::failbit); \ 931 #define BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying) 934 #define BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying) \ 937 #if defined(_MSC_VER) && _MSC_VER >= 1700 940 # define BETTER_ENUMS_LEGACY_UNDERLYING_TYPE(Underlying) BETTER_ENUMS_CXX11_UNDERLYING_TYPE(Underlying) 942 # define BETTER_ENUMS_LEGACY_UNDERLYING_TYPE(Underlying) BETTER_ENUMS_CXX98_UNDERLYING_TYPE(Underlying) 946 #define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE(Type) \ 950 #define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE(Type) \ 951 BETTER_ENUMS_NS(Type)::_enumClassForSwitchStatements 954 #define BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE(Underlying, ...) 957 #define BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE(Underlying, ...) \ 958 enum class _enumClassForSwitchStatements : Underlying { __VA_ARGS__ }; 961 #define BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS(Enum, ...) \ 962 inline const char** _raw_names() \ 964 static const char *value[] = \ 965 { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) }; \ 969 inline char* _name_storage() \ 971 static char storage[] = \ 972 BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__)); \ 976 inline const char** _name_array() \ 978 static const char *value[Enum::_size_constant]; \ 982 inline bool& _initialized() \ 984 static bool value = false; \ 989 #define BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...) \ 990 constexpr const char *_the_raw_names[] = \ 991 { BETTER_ENUMS_ID(BETTER_ENUMS_STRINGIZE(__VA_ARGS__)) }; \ 993 constexpr const char * const * _raw_names() \ 995 return _the_raw_names; \ 998 inline char* _name_storage() \ 1000 static char storage[] = \ 1001 BETTER_ENUMS_ID(BETTER_ENUMS_RESERVE_STORAGE(__VA_ARGS__)); \ 1005 inline const char** _name_array() \ 1007 static const char *value[Enum::_size_constant]; \ 1011 inline bool& _initialized() \ 1013 static bool value = false; \ 1018 #define BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS(Enum, ...) \ 1019 BETTER_ENUMS_ID(BETTER_ENUMS_TRIM_STRINGS(__VA_ARGS__)) \ 1021 constexpr const char * const _the_name_array[] = \ 1022 { BETTER_ENUMS_ID(BETTER_ENUMS_REFER_TO_STRINGS(__VA_ARGS__)) }; \ 1024 constexpr const char * const * _name_array() \ 1026 return _the_name_array; \ 1029 constexpr const char * const * _raw_names() \ 1031 return _the_name_array; \ 1035 #define BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD 1038 #define BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD \ 1042 #define BETTER_ENUMS_DO_DECLARE_INITIALIZE \ 1043 static int initialize(); 1046 #define BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE \ 1047 static int initialize() { return 0; } 1050 #define BETTER_ENUMS_DO_DEFINE_INITIALIZE(Enum) \ 1051 inline int Enum::initialize() \ 1053 if (BETTER_ENUMS_NS(Enum)::_initialized()) \ 1056 ::better_enums::_trim_names(BETTER_ENUMS_NS(Enum)::_raw_names(), \ 1057 BETTER_ENUMS_NS(Enum)::_name_array(), \ 1058 BETTER_ENUMS_NS(Enum)::_name_storage(), \ 1061 BETTER_ENUMS_NS(Enum)::_initialized() = true; \ 1067 #define BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE(Enum) 1070 #define BETTER_ENUMS_DO_CALL_INITIALIZE(value) \ 1071 ::better_enums::continue_with(initialize(), value) 1074 #define BETTER_ENUMS_DO_NOT_CALL_INITIALIZE(value) \ 1081 #ifdef BETTER_ENUMS_STRICT_CONVERSION 1082 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE \ 1083 BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE 1084 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE \ 1085 BETTER_ENUMS_ENUM_CLASS_SWITCH_TYPE_GENERATE 1087 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE \ 1088 BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE 1089 # define BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE \ 1090 BETTER_ENUMS_REGULAR_ENUM_SWITCH_TYPE_GENERATE 1095 #ifndef BETTER_ENUMS_DEFAULT_CONSTRUCTOR 1096 # define BETTER_ENUMS_DEFAULT_CONSTRUCTOR(Enum) \ 1098 Enum() : _value(0) { } 1103 #ifdef BETTER_ENUMS_HAVE_CONSTEXPR 1105 #ifdef BETTER_ENUMS_CONSTEXPR_TO_STRING 1106 # define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS \ 1107 BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS 1108 # define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD \ 1109 BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD 1110 # define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE \ 1111 BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE 1112 # define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE \ 1113 BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE 1114 # define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE \ 1115 BETTER_ENUMS_DO_NOT_CALL_INITIALIZE 1117 # define BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS \ 1118 BETTER_ENUMS_CXX11_PARTIAL_CONSTEXPR_TRIM_STRINGS_ARRAYS 1119 # define BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD \ 1120 BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD 1121 # define BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE \ 1122 BETTER_ENUMS_DO_DECLARE_INITIALIZE 1123 # define BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE \ 1124 BETTER_ENUMS_DO_DEFINE_INITIALIZE 1125 # define BETTER_ENUMS_DEFAULT_CALL_INITIALIZE \ 1126 BETTER_ENUMS_DO_CALL_INITIALIZE 1133 #define BETTER_ENUM(Enum, Underlying, ...) \ 1134 BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \ 1135 BETTER_ENUMS_CXX11_UNDERLYING_TYPE, \ 1136 BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \ 1137 BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \ 1138 BETTER_ENUMS_DEFAULT_TRIM_STRINGS_ARRAYS, \ 1139 BETTER_ENUMS_DEFAULT_TO_STRING_KEYWORD, \ 1140 BETTER_ENUMS_DEFAULT_DECLARE_INITIALIZE, \ 1141 BETTER_ENUMS_DEFAULT_DEFINE_INITIALIZE, \ 1142 BETTER_ENUMS_DEFAULT_CALL_INITIALIZE, \ 1143 Enum, Underlying, __VA_ARGS__)) 1145 #define SLOW_ENUM(Enum, Underlying, ...) \ 1146 BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \ 1147 BETTER_ENUMS_CXX11_UNDERLYING_TYPE, \ 1148 BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \ 1149 BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \ 1150 BETTER_ENUMS_CXX11_FULL_CONSTEXPR_TRIM_STRINGS_ARRAYS, \ 1151 BETTER_ENUMS_CONSTEXPR_TO_STRING_KEYWORD, \ 1152 BETTER_ENUMS_DECLARE_EMPTY_INITIALIZE, \ 1153 BETTER_ENUMS_DO_NOT_DEFINE_INITIALIZE, \ 1154 BETTER_ENUMS_DO_NOT_CALL_INITIALIZE, \ 1155 Enum, Underlying, __VA_ARGS__)) 1159 #define BETTER_ENUM(Enum, Underlying, ...) \ 1160 BETTER_ENUMS_ID(BETTER_ENUMS_TYPE( \ 1161 BETTER_ENUMS_LEGACY_UNDERLYING_TYPE, \ 1162 BETTER_ENUMS_DEFAULT_SWITCH_TYPE, \ 1163 BETTER_ENUMS_DEFAULT_SWITCH_TYPE_GENERATE, \ 1164 BETTER_ENUMS_CXX98_TRIM_STRINGS_ARRAYS, \ 1165 BETTER_ENUMS_NO_CONSTEXPR_TO_STRING_KEYWORD, \ 1166 BETTER_ENUMS_DO_DECLARE_INITIALIZE, \ 1167 BETTER_ENUMS_DO_DEFINE_INITIALIZE, \ 1168 BETTER_ENUMS_DO_CALL_INITIALIZE, \ 1169 Enum, Underlying, __VA_ARGS__)) 1179 template <
typename T>
1181 BETTER_ENUMS_CONSTEXPR_
static bool less(
const T& a,
const T& b)
1187 BETTER_ENUMS_CONSTEXPR_
static bool less(
const char *a,
const char *b)
1188 {
return less_loop(a, b); }
1191 BETTER_ENUMS_CONSTEXPR_
static bool 1192 less_loop(
const char *a,
const char *b,
size_t index = 0)
1195 a[index] != b[index] ? a[index] < b[index] :
1196 a[index] ==
'\0' ? false :
1197 less_loop(a, b, index + 1);
1204 BETTER_ENUMS_CONSTEXPR_
static bool less(
const wchar_t *a,
const wchar_t *b)
1205 {
return less_loop(a, b); }
1208 BETTER_ENUMS_CONSTEXPR_
static bool 1209 less_loop(
const wchar_t *a,
const wchar_t *b,
size_t index = 0)
1212 a[index] != b[index] ? a[index] < b[index] :
1213 a[index] == L
'\0' ? false :
1214 less_loop(a, b, index + 1);
1218 template <
typename Enum,
typename T,
typename Compare = map_compare<T> >
1220 typedef T (*
function)(Enum);
1222 BETTER_ENUMS_CONSTEXPR_
explicit map(
function f) : _f(f) { }
1224 BETTER_ENUMS_CONSTEXPR_ T from_enum(Enum value)
const {
return _f(value); }
1225 BETTER_ENUMS_CONSTEXPR_ T operator [](Enum value)
const 1226 {
return _f(value); }
1228 BETTER_ENUMS_CONSTEXPR_ Enum to_enum(T value)
const 1231 _or_throw(to_enum_nothrow(value),
"map::to_enum: invalid argument");
1235 to_enum_nothrow(T value,
size_t index = 0)
const 1239 Compare::less(_f(Enum::_values()[index]), value) ||
1240 Compare::less(value, _f(Enum::_values()[index])) ?
1241 to_enum_nothrow(value, index + 1) :
1242 Enum::_values()[index];
1249 template <
typename Enum,
typename T>
1250 BETTER_ENUMS_CONSTEXPR_
map<Enum, T> make_map(T (*f)(Enum))
1257 #endif // #ifndef BETTER_ENUMS_ENUM_H