MRDOCS_DESCRIBE_KINDS_BEGIN

Open a kinds description driven by an X-macro .inc file.

Synopsis

Declared in <mrdocs/Support/Reflection/Describe.hpp>

#define MRDOCS_DESCRIBE_KINDS_BEGIN(C)

Description

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.

Parameters

NameDescription
CThe polymorphic base class.