Open a kinds description driven by an X-macro .inc file.
Declared in <mrdocs/Support/Reflection/Describe.hpp>
#define MRDOCS_DESCRIBE_KINDS_BEGIN(C)
When the derived kinds already live in an X-macro .inc file (one INFO(Name) per kind, often the same file that builds the kind enum), this registers them without repeating the list in MRDOCS_DESCRIBE_KINDS. Point INFO at MRDOCS_KIND_ENTRY, then bracket the include with this macro and MRDOCS_DESCRIBE_KINDS_END. Given this ShapeNodes.inc:
#ifndef INFO
#define INFO(Name)
#endif
INFO(Circle)
INFO(Square)
#undef INFO
a header can build both the enum and the kind list from it:
namespace shapes {
enum class ShapeKind
{
#define INFO(Name) Name,
#include "ShapeNodes.inc"
};
struct Shape { ShapeKind Kind; };
struct CircleShape : Shape
{
static constexpr ShapeKind kind_id = ShapeKind::Circle;
CircleShape() : Shape{kind_id} {}
};
struct SquareShape : Shape
{
static constexpr ShapeKind kind_id = ShapeKind::Square;
SquareShape() : Shape{kind_id} {}
};
#define INFO(Name) MRDOCS_KIND_ENTRY(Shape, Name##Shape)
MRDOCS_DESCRIBE_KINDS_BEGIN(Shape)
#include "ShapeNodes.inc"
MRDOCS_DESCRIBE_KINDS_END(Shape)
} // namespace shapes
The entries can also be written by hand, and an empty pair registers a base with no kinds:
MRDOCS_DESCRIBE_KINDS_BEGIN(Node)
MRDOCS_KIND_ENTRY(Node, Leaf)
MRDOCS_KIND_ENTRY(Node, Branch)
MRDOCS_DESCRIBE_KINDS_END(Node)
MRDOCS_DESCRIBE_KINDS_BEGIN(Empty)
MRDOCS_DESCRIBE_KINDS_END(Empty)
After preprocessing, the Shape block becomes the following (simplified: the ::mrdocs::describe::detail:: qualification is dropped and the assertion message is shortened):
// MRDOCS_DESCRIBE_KINDS_BEGIN(Shape): leaves the call open
static_assert(std::is_class_v<Shape>, "...");
[[maybe_unused]]
inline decltype(kind_descriptor_fn_impl(0
// #include "ShapeNodes.inc": one MRDOCS_KIND_ENTRY per INFO line
, kind_descriptor<Shape, CircleShape>{} // INFO(Circle)
, kind_descriptor<Shape, SquareShape>{} // INFO(Square)
// MRDOCS_DESCRIBE_KINDS_END(Shape): closes the call
)) mrdocs_kind_descriptor_fn(Shape**) { return {}; }
That's the same declaration MRDOCS_DESCRIBE_KINDS(Shape, CircleShape, SquareShape) produces, so the same queries (describe::describe_kinds, describe::has_describe_kinds, mrdocs::visit) work afterwards.
Things to keep in mind:
This macro leaves a call open, so only MRDOCS_KIND_ENTRY expansions and preprocessor directives may come before the matching MRDOCS_DESCRIBE_KINDS_END. Anything else, including a stray ;, is a syntax error.
Pass the same base to this macro, to every entry, and to MRDOCS_DESCRIBE_KINDS_END.
Place the block at namespace scope, in the namespace of the base.
Define INFO before the include. The .inc file is expected to #undef it at the end; if yours doesn't, add the #undef yourself.
| Name | Description |
|---|---|
| C | The polymorphic base class. |