[#MRDOCS_DESCRIBE_ENUM_BEGIN] = MRDOCS_DESCRIBE_ENUM_BEGIN :mrdocs: Open an enum description driven by an X‐macro `.inc` file. == Synopsis Declared in `<mrdocs/Support/Reflection/Describe.hpp>` [source,cpp,subs="verbatim,replacements,macros,-callouts"] ---- #define MRDOCS_DESCRIBE_ENUM_BEGIN(E) ---- == Description Use it when the enumerators already live in an X‐macro `.inc` file, one `INFO(Name)` line per enumerator, that also defines the enum. You then describe the enum from the same list instead of repeating every name in `MRDOCS_DESCRIBE_ENUM`, so the two can't drift apart. Given this `ShapeNodes.inc`: [,cpp] ---- #ifndef INFO #define INFO(Name) #endif INFO(Circle) INFO(RoundedRect) INFO(Triangle) #undef INFO ---- include it once to define the enum and once more between `MRDOCS_DESCRIBE_ENUM_BEGIN` and `MRDOCS_DESCRIBE_ENUM_END`, with `INFO` pointed at `MRDOCS_ENUM_ENTRY`: [,cpp] ---- namespace shapes { enum class ShapeKind { None = 0, #define INFO(Name) Name, #include "ShapeNodes.inc" }; MRDOCS_DESCRIBE_ENUM_BEGIN(ShapeKind) #define INFO(Name) MRDOCS_ENUM_ENTRY(ShapeKind, Name) #include "ShapeNodes.inc" MRDOCS_DESCRIBE_ENUM_END(ShapeKind) } // namespace shapes ---- The `.inc` file `#undef`s `INFO` itself, so no cleanup line is needed. The three pieces together produce the same declaration as `MRDOCS_DESCRIBE_ENUM(ShapeKind, Circle, RoundedRect, Triangle)`: [,cpp] ---- // Simplified: each lambda is a distinct closure type that returns the // stringized name. // MRDOCS_DESCRIBE_ENUM_BEGIN(ShapeKind) static_assert(std::is_enum_v, "MRDOCS_DESCRIBE_ENUM should only be used with enums"); [[maybe_unused]] decltype(::mrdocs::describe::detail::enum_descriptor_fn_impl(0 // #include "ShapeNodes.inc": one MRDOCS_ENUM_ENTRY per INFO line , ::mrdocs::describe::detail::enum_descriptor< ShapeKind::Circle, []{ return "Circle"; }>{} , ::mrdocs::describe::detail::enum_descriptor< ShapeKind::RoundedRect, []{ return "RoundedRect"; }>{} , ::mrdocs::describe::detail::enum_descriptor< ShapeKind::Triangle, []{ return "Triangle"; }>{} // MRDOCS_DESCRIBE_ENUM_END(ShapeKind) )) mrdocs_enum_descriptor_fn(ShapeKind**); ---- Here `None` isn't in the `.inc` file, so it isn't described: `toString(ShapeKind::None)` is empty, while `toString(ShapeKind::RoundedRect)` is `"rounded‐rect"`. Things to keep in mind: * The macro opens a parenthesized expression that `MRDOCS_DESCRIBE_ENUM_END` closes, so everything in between must expand to nothing but `MRDOCS_ENUM_ENTRY` calls (and preprocessor directives). Each entry starts with its own comma, so don't add separators. * Pass the same enum type to both macros. * The placement rules of `MRDOCS_DESCRIBE_ENUM` apply: namespace scope, in the namespace of the enum, never inside a class. * Don't put a `;` after either macro. After this one it's a syntax error, and `MRDOCS_DESCRIBE_ENUM_END` already ends with one. * Unlike `MRDOCS_DESCRIBE_ENUM`, there's no limit on the number of enumerators. == Parameters [cols="1,4"] |=== | Name| Description | *E* | The enum type. |=== [.small]#Created with https://www.mrdocs.com[MrDocs]#