mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
Purged out-of-date documentation.
This commit is contained in:
parent
216f026fe1
commit
3ac5e84cf9
135
enum.h
135
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 <cstddef> // 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 <typename EnumType, typename Iterator>
|
||||
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<UnderlyingType>)A
|
||||
/// (_eat_assign<UnderlyingType>)A = 42
|
||||
/// ~~~
|
||||
/// The second case is the interesting one. At compile time, the value `A` is
|
||||
/// first converted to an equivalent `_eat_assign<UnderlyingType>` 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 <typename UnderlyingType>
|
||||
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<UnderlyingType>)`
|
||||
/// in order to make it usable in initializer lists. See `_eat_assign`.
|
||||
#define _ENUM_EAT_ASSIGN_SINGLE(UnderlyingType, expression) \
|
||||
((_enum::_eat_assign<UnderlyingType>)UnderlyingType::expression)
|
||||
|
||||
/// Prepends each of its arguments with the casts
|
||||
/// `(_eat_assign<UnderlyingType>)`, 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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user