diff --git a/enum.h b/enum.h index c33d679..bf9491f 100644 --- a/enum.h +++ b/enum.h @@ -1,32 +1,3 @@ -/// @file EnumInternal.h -/// Internal definitions for the enum type generator in `Enum.h`. -/// -/// Several definitions must precede the public `ENUM` macro and the interface -/// defined in it. This includes helper classes and all `constexpr` functions, -/// which cannot be forward-declared. In order to make `Enum.h` more readable, -/// these definitions are placed into this file, which is included from -/// `Enum.h`. -/// -/// Throughout the internal code, macro and template parameters named `EnumType` -/// stand for the class types generated by the `ENUM` macro, while parameters -/// named `EnumValue` stand for the internal C++ enum types. Roughly, -/// `EnumValue == EnumType::_Value`. -/// -/// @todo Generating the values array using the `_eat_assign` template is -/// expensive, and the cost seems to be due to the instantiation of -/// compile-time objects, not due to templates. Trying statement expressions -/// (a GNU extension) didn't work, because statement expressions aren't -/// allowed "at file scope" (in this case, within a class type declared at -/// file scope). -/// @todo Compile time is currently dominated by the cost of static -/// instantiation. Try to reduce this cost by statically instantiating data -/// structures for each type, then dynamically passing them to a small -/// number of actual processing functions - which only have to be -/// instantiated once for every different underlying type. Underlying types -/// are very likely to collide. - - - #pragma once #include // For size_t. @@ -38,59 +9,14 @@ -/// Internal namespace for compile-time and private run-time functions used by -/// the enum class generator. namespace _enum { -/// Weak symbols to allow the same data structures to be defined statically in -/// multiple translation units, then be collapsed to one definition by the -/// linker. #define _ENUM_WEAK __attribute__((weak)) -/// Template for iterable objects over enum names and values. -/// -/// The iterables are intended for use with C++11 `for-each` syntax. They are -/// returned by each enum type's static `names()` and `values()` methods. For -/// example, `EnumType::values()` is an iterable over valid values of type -/// `EnumType`, and allows the following form: -/// -/// ~~~{.cc} -/// for (EnumType e : EnumType::values()) { -/// // ... -/// } -/// ~~~ -/// -/// The iterable class is templated to reuse code between the name and value -/// iterables. -/// -/// @tparam Element Type of element returned during iteration: either the enum -/// type (for iterables over `values()`) or `const char*` (for iterables -/// over `names()`). -/// @tparam EnumType The enum type. -/// @tparam ArrayType Type of the array actually being iterated over. The reason -/// this is a type parameter is because for the iterable over `values()`, -/// the underlying array type is `const EnumType::_value * const`, instead -/// of `const EnumType * const`, as one might first expect. Objects of type -/// `EnumType` are constructed on the fly during iteration from values of -/// type `EnumType::_value` (this is a no-op at run-time). For iterables -/// over `names()`, `ArrayType` is simply `const char * const`, as would be -/// expeted. -/// -/// @internal -/// -/// An `_Iterable` stores a reference to the array (of either names or values) -/// that will be iterated over. `_Iterable::iterator` additionally stores an -/// index into the array. The iterator begins at the first valid index. Each -/// time it is incremented, the iterator advances to the next valid index. The -/// `end()` iterator stores an index equal to the size of the array. Values are -/// considered valid if they are not equal to the bad value, are not below the -/// minimum value, and are not above the maximum value. Names are valid if they -/// are the name of a valid value. - template class _Iterable; @@ -159,23 +85,6 @@ class _Iterable { -/// Compile-time helper class used to transform expressions of the forms `A` and -/// `A = 42` into values of type `UnderlyingType` that can be used in -/// initializer lists. The `ENUM` macro is passed a mixture of simple enum -/// constants (`A`) and constants with an explicitly-assigned value (`A = 42`). -/// Both must be turned into expressions of type `UnderlyingType` in order to be -/// usable in initializer lists of the values array. This is done by prepending -/// a cast to the expression, as follows: -/// ~~~{.cc} -/// (_eat_assign)A -/// (_eat_assign)A = 42 -/// ~~~ -/// The second case is the interesting one. At compile time, the value `A` is -/// first converted to an equivalent `_eat_assign` object, that -/// stores the value. This object has an overriden assignment operator, which -/// "eats" the `= 42` and returns the stored value of `A`, which is then used in -/// the initializer list. -/// @tparam UnderlyingType Final type used in the values array. template class _eat_assign { private: @@ -189,55 +98,23 @@ class _eat_assign { constexpr operator UnderlyingType () const { return _value; } }; -/// Prepends its second argument with the cast `(_eat_assign)` -/// in order to make it usable in initializer lists. See `_eat_assign`. #define _ENUM_EAT_ASSIGN_SINGLE(UnderlyingType, expression) \ ((_enum::_eat_assign)UnderlyingType::expression) -/// Prepends each of its arguments with the casts -/// `(_eat_assign)`, creating the elements of an initializer -/// list of objects of type `UnderlyingType`. #define _ENUM_EAT_ASSIGN(UnderlyingType, ...) \ _ENUM_PP_MAP(_ENUM_EAT_ASSIGN_SINGLE, UnderlyingType, __VA_ARGS__) -/// Stringizes its second argument. The first argument is not used - it is there -/// only because `_ENUM_PP_MAP` expects it. #define _ENUM_STRINGIZE_SINGLE(ignored, expression) #expression -/// Stringizes each of its arguments. #define _ENUM_STRINGIZE(...) \ _ENUM_PP_MAP(_ENUM_STRINGIZE_SINGLE, ignored, __VA_ARGS__) -/// Symbols that end a constant name. Constant can be defined in several ways, -/// for example: -/// ~~~{.cc} -/// A -/// A = AnotherConstant -/// A = 42 -/// A=42 -/// ~~~ -/// These definitions are stringized in their entirety by `_ENUM_STRINGIZE`. -/// This means that in addition to the actual constant names, the raw `_names` -/// arrays potentially contain additional trailing symbols. `_ENUM_NAME_ENDERS` -/// defines an array of symbols that would end the part of the string that is -/// the actual constant name. Note that it is important that the null terminator -/// is implicitly present in this array. #define _ENUM_NAME_ENDERS "= \t\n" -/// Compile-time function that determines whether a character terminates the -/// name portion of an enum constant definition. -/// -/// Call as `_endsName(c)`. -/// -/// @param c Character to be tested. -/// @param index Current index into the `_ENUM_NAME_ENDERS` array. -/// @return `true` if and only if `c` is one of the characters in -/// `_ENUM_NAME_ENDERS`, including the implicit null terminator in that -/// array. constexpr bool _endsName(char c, size_t index = 0) { return @@ -258,18 +135,6 @@ constexpr char _toLowercaseAscii(char c) return c >= 0x41 && c <= 0x5A ? c + 0x20 : c; } -/// Compile-time function that matches a stringized name (with potential -/// trailing spaces and equals signs) against a reference name (a regular -/// null-terminated string). -/// -/// Call as `_namesMatch(stringizedName, referenceName)`. -/// -/// @param stringizedName A stringized constant name, potentially terminated by -/// one of the symbols in `_ENUM_NAME_ENDERS` instead of a null terminator. -/// @param referenceName A name of interest. Null-terminated. -/// @param index Current index into both names. -/// @return `true` if and only if the portion of `stringizedName` before any of -/// the symbols in `_ENUM_NAME_ENDERS` exactly matches `referenceName`. constexpr bool _namesMatch(const char *stringizedName, const char *referenceName, size_t index = 0)