MRDOCS_DESCRIBE_ENUM_BEGIN

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

Synopsis

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

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

NameDescription
EThe enum type.