MRDOCS_DESCRIBE_ENUM

Describe the enumerators of an enum.

Synopsis

#define MRDOCS_DESCRIBE_ENUM(E, …​)

Description

Pass the enum type followed by the enumerators you want to describe, up to 128 of them. Place it at namespace scope, in the same namespace as the enum, after the enum definition:

namespace shapes {

enum class Shape { Circle, RoundedRect, Triangle };

MRDOCS_DESCRIBE_ENUM(Shape, Circle, RoundedRect, Triangle)

} // namespace shapes

The macro declares a function that is found by argument‐dependent lookup and whose return type lists one descriptor per enumerator:

// Simplified: whitespace changed; each lambda is a distinct closure
// type that only returns the stringized enumerator name.

// MRDOCS_DESCRIBE_ENUM(Shape, Circle, RoundedRect, Triangle)
static_assert(std::is_enum_v<Shape>,
    "MRDOCS_DESCRIBE_ENUM should only be used with enums");
[[maybe_unused]]
decltype(::mrdocs::describe::detail::enum_descriptor_fn_impl(0
    , ::mrdocs::describe::detail::enum_descriptor<
        Shape::Circle, []{ return "Circle"; }>{}
    , ::mrdocs::describe::detail::enum_descriptor<
        Shape::RoundedRect, []{ return "RoundedRect"; }>{}
    , ::mrdocs::describe::detail::enum_descriptor<
        Shape::Triangle, []{ return "Triangle"; }>{}
)) mrdocs_enum_descriptor_fn(Shape**);
// The return type is describe::list<D1, D2, D3>, where each Di has
// `static constexpr Shape value` and `static constexpr char const*
// name`. The function is declared only; it's never called.

Afterwards the enum works with the describe queries and the string helpers, all usable in constant expressions:

namespace describe = mrdocs::describe;
using shapes::Shape;

static_assert(describe::has_describe_enumerators<Shape>::value);

// Kebab-case name, as used in the generated output
static_assert(mrdocs::toString(Shape::RoundedRect) == "rounded-rect");

// Declared name
static_assert(
    describe::enum_to_string(Shape::RoundedRect) == "RoundedRect");

void
demo()
{
    // Declared name back to the enumerator
    Shape s{};
    bool ok = describe::enum_from_string("Triangle", s);
    // ok == true, s == Shape::Triangle

    // Visit every described enumerator
    describe::for_each(
        describe::describe_enumerators<Shape>{},
        [](auto d) {
            // d.value: Shape::Circle, then RoundedRect, then Triangle
            // d.name:  "Circle", then "RoundedRect", then "Triangle"
        });
}

Things to keep in mind:

  • Don't put it inside a class, even for a nested enum. There it declares a member function that lookup never finds, so the enum silently stays undescribed. For a nested enum, write it at namespace scope after the class and qualify the type: MRDOCS_DESCRIBE_ENUM(Canvas::Layer, background, foreground).

  • Writing it in a different namespace also leaves the enum undescribed, for the same reason.

  • It already ends with a semicolon, so don't add one.

  • Enumerators you leave out are unknown to the helpers: toString and describe::enum_to_string return an empty string for them, and describe::enum_from_string never produces them.

  • Works for scoped and unscoped enums, since each entry is spelled E::name.

  • When the enumerators already live in an X‐macro .inc file, use MRDOCS_DESCRIBE_ENUM_BEGIN and MRDOCS_DESCRIBE_ENUM_END instead. They also have no limit on the number of enumerators.

  • To mark one enumerator as the empty state, follow it with MRDOCS_DESCRIBE_ENUM_UNDEFINED.

Parameters

Name

Description

E

The enum type.

Created with MrDocs