MRDOCS_DESCRIBE_ENUM_BEGIN

Open an enum description driven by an X‐macro .inc file.

Synopsis

#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:

#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:

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):

// Simplified: each lambda is a distinct closure type that returns the
// stringized name.

// MRDOCS_DESCRIBE_ENUM_BEGIN(ShapeKind)
static_assert(std::is_enum_v<ShapeKind>,
    "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

Name

Description

E

The enum type.

Created with MrDocs